windows 臨界區

來源:互聯網
上載者:User

接上一篇,我們來看另一種實現臨界區順序訪問的方法
這次我們使用,InitializeCriticalSection, EnterCriticalSection,LeaveCriticalSection,DeleteCriticalSection
要使用這些需要包含windows.h並定義一個CRITICAL_SECTION變數
那麼這種方式與上一篇中用互斥量實現的方式有什麼差別呢?
下面是實現的代碼:

View Code

#pragma once#include <windows.h>#include <assert.h>class CVCriSection{public:    CVCriSection(void);    ~CVCriSection(void);public:    int CsEnter()    {        EnterCriticalSection(&m_cs);         return 0;    }    int CsLeave()    {        LeaveCriticalSection(&m_cs);         return 0;    }protected:    CRITICAL_SECTION m_cs;};class CVCriSectionAuto{public:        CVCriSectionAuto(CVCriSection* cs)    {        m_cs=cs;         m_cs->CsEnter();            }    ~CVCriSectionAuto(void)    {        m_cs->CsLeave();        m_cs=NULL;    }private:    CVCriSection* m_cs;};CVCriSection::CVCriSection(void){    InitializeCriticalSection(&m_cs);}CVCriSection::~CVCriSection(void){    DeleteCriticalSection(&m_cs);}

有如下的測試代碼

CVCriSection cs;int sum=0;int last=0;pthread_mutex_t g_mutex = CreateMutex(NULL, FALSE, NULL);DWORD WINAPI worker(LPVOID lpParameter){    int no= (int)lpParameter;    last = no;    while (1)    {        CVCriSectionAuto csauto(&cs); //方式1        //CCriticalSection cs(g_mutex); //方式2,這種方式下會嚴格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3個線程具有均等的運行機會        //cs.CsEnter();        sum=0;        for (int i=0; i<=100000; i++)            sum += i;        if (no != (last+1)%3)            printf("not equal\n");        last = no;        //cs.CsLeave();    }}int main(){    for (int i=0; i<3; i++)        CreateThread(NULL, 0, worker, (LPVOID)i, 0, NULL);    Sleep(20000);    return 0;}

當使用方式1(使用CRITICAL_SECTION實現)來實現互斥訪問時,上面的代碼將會有很多not equal輸出。這就是說,三個線程執行的次數是隨機的
當使用方式2(使用互斥量實現)來實現互斥訪問時,上面的代碼將不會有not equal輸出。也就是說,三個線程得到了均等的運行機會。它們訪問臨界區的次數是相當的。
下面的測試代碼可以更直觀的看出它們的差別:

CVCriSection cs;int sum=0;int last=0;int cnt[3] = {0, 0, 0};pthread_mutex_t g_mutex = CreateMutex(NULL, FALSE, NULL);DWORD WINAPI worker(LPVOID lpParameter){    int no= (int)lpParameter;    last = no;    while (1)    {        //CVCriSectionAuto csauto(&cs); //方式1        CCriticalSection cs(g_mutex); //方式2,這種方式下會嚴格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3個線程具有均等的運行機會        //cs.CsEnter();        sum=0;        for (int i=0; i<=100000; i++)            sum += i;        cnt[no]++;        //cs.CsLeave();    }}int main(){    for (int i=0; i<3; i++)        CreateThread(NULL, 0, worker, (LPVOID)i, 0, NULL);    Sleep(5000);    for (int j=0; j<3; j++)        printf("%d\n", cnt[j]);    return 0;}

最後分別輸出三個線程分別進入臨界區的次數。

總結:
用CRITICAL_SECTION實現的方式,線程訪問臨界區的次數基本上是和線程本身執行的快慢成正比的
用互斥量實現的方式,線程訪問臨界區的次數基本上是相等的。
所以要根據實際使用的情境選擇合適的方式
進一步可有用下面的代碼來驗證上面的結論

View Code

CVCriSection cs;int sum=0;int last=0;int cnt[3] = {0, 0, 0};pthread_mutex_t g_mutex = CreateMutex(NULL, FALSE, NULL);DWORD WINAPI worker(LPVOID lpParameter){    int no= (int)lpParameter;    last = no;    while (1)    {        CVCriSectionAuto csauto(&cs); //方式1        //CCriticalSection cs(g_mutex); //方式2,這種方式下會嚴格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3個線程具有均等的運行機會        //cs.CsEnter();        sum=0;        int add = no*1000;        for (int i=0; i<=10000+add; i++)            sum += i;        cnt[no]++;        //cs.CsLeave();    }}int main(){    for (int i=0; i<3; i++)        CreateThread(NULL, 0, worker, (LPVOID)i, 0, NULL);    Sleep(5000);    for (int j=0; j<3; j++)        printf("%d %d\n", j, cnt[j]);    return 0;}

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.