生活随笔
收集整理的這篇文章主要介紹了
windows 临界区
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
接上一篇,我們來看另一種實現臨界區順序訪問的方法
這次我們使用,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); //方式1CCriticalSection 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;
} ?
?
?
總結
以上是生活随笔為你收集整理的windows 临界区的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。