生活随笔
收集整理的這篇文章主要介紹了
windows 临界区
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
接上一篇,我們來看另一種實(shí)現(xiàn)臨界區(qū)順序訪問的方法
這次我們使用,InitializeCriticalSection,?EnterCriticalSection,LeaveCriticalSection,DeleteCriticalSection
要使用這些需要包含windows.h并定義一個(gè)CRITICAL_SECTION變量
那么這種方式與上一篇中用互斥量實(shí)現(xiàn)的方式有什么差別呢?
下面是實(shí)現(xiàn)的代碼:
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);
} 有如下的測(cè)試代碼
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,這種方式下會(huì)嚴(yán)格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3個(gè)線程具有均等的運(yùn)行機(jī)會(huì)//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;
} 當(dāng)使用方式1(使用CRITICAL_SECTION實(shí)現(xiàn))來實(shí)現(xiàn)互斥訪問時(shí),上面的代碼將會(huì)有很多not equal輸出。這就是說,三個(gè)線程執(zhí)行的次數(shù)是隨機(jī)的
當(dāng)使用方式2(使用互斥量實(shí)現(xiàn))來實(shí)現(xiàn)互斥訪問時(shí),上面的代碼將不會(huì)有not equal輸出。也就是說,三個(gè)線程得到了均等的運(yùn)行機(jī)會(huì)。它們?cè)L問臨界區(qū)的次數(shù)是相當(dāng)?shù)摹?br />下面的測(cè)試代碼可以更直觀的看出它們的差別:
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,這種方式下會(huì)嚴(yán)格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3個(gè)線程具有均等的運(yùn)行機(jī)會(huì)//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;
} 最后分別輸出三個(gè)線程分別進(jìn)入臨界區(qū)的次數(shù)。
總結(jié):
用CRITICAL_SECTION實(shí)現(xiàn)的方式,線程訪問臨界區(qū)的次數(shù)基本上是和線程本身執(zhí)行的快慢成正比的
用互斥量實(shí)現(xiàn)的方式,線程訪問臨界區(qū)的次數(shù)基本上是相等的。
所以要根據(jù)實(shí)際使用的場(chǎng)景選擇合適的方式
進(jìn)一步可有用下面的代碼來驗(yàn)證上面的結(jié)論
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,這種方式下會(huì)嚴(yán)格按照0, 1, 2, 0, 1, 2 .... 或 1, 0, 2, 1, 0, 2 等, 既3個(gè)線程具有均等的運(yùn)行機(jī)會(huì)//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;
} ?
?
?
總結(jié)
以上是生活随笔為你收集整理的windows 临界区的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。