一 win32 臨界區
臨界區是一種防止多個線程同時執行一個特定代碼段的機制。如果有多個線程試圖同時訪問臨界區,那麼在有一個線程進入後其他的所有試圖訪問此臨界區的線程將被掛起,並且一直持續到進入臨界區的線程離開。
臨界區適用於多個線程操作之間沒有先後順序但要求互斥的同步。
多個線程訪問同一個臨界區的原則:
1、一次最多隻能一個線程停留在臨界區內。
2、不能讓一個線程無限的停留在臨界區內,否則其它線程將不能進入臨界區。
定義臨界區變量的方法如下:
CRITICAL_SECTION critical_section;
通常情況下,CRITICAL_SECTION結構體應該被定義爲全局變量,便於進程中的所有線程可以按照變量名來引用此結構體。
相關的API包括:
初始化臨界區:
VOID WINAPI InitializeCriticalSection(LPCIRITICAL_SECTION lpCriticalSection);
刪除臨界區:
VOID WINAPI DeleteCriticalSection(LPCIRITICAL_SECTION lpCriticalSection);
進入臨界區:
VOID WINAPI EnterCriticalSection(LPCIRITICAL_SECTION lpCriticalSection);
離開臨界區:
VOID WINAPI LeaveCriticalSection(LPCIRITICAL_SECTION lpCriticalSection);
使用臨界區的一般方法是:
void WriteData()
{
EnterCriticalSection(&critical_section);
doSomething();
LeaveCriticalSection(&critical_section);
}
二 實例
#include <windows.h>
int total = 100;
HANDLE evhandle[2];
CRITICAL_SECTION cs;
void WithDrawThread1(LPVOID param)
{
EnterCriticalSection(&cs);
if (total - 90 >= 0)
{
total -= 90;
MessageBox(NULL,"You get $90",TEXT("線程1"),0);
}
else
{
MessageBox(NULL,"You haven't right to withdraw so much money",TEXT("線程1"),0);
}
LeaveCriticalSection(&cs);
SetEvent(evhandle[0]);
}
void WithDrawThread2(LPVOID param)
{
EnterCriticalSection(&cs);
if (total - 20 >= 0)
{
total -= 20;
MessageBox(NULL,"You get $20",TEXT("線程2"),0);
}
else
{
MessageBox(NULL,"You haven't right to withdraw so much money",TEXT("線程2"),0);
}
LeaveCriticalSection(&cs);
SetEvent(evhandle[1]);
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
/* TODO: Place code here. by bo*/
char szBuffer[100];
evhandle[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
evhandle[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
InitializeCriticalSection(&cs);
_beginthread(WithDrawThread1,0,NULL);
_beginthread(WithDrawThread2,0,NULL);
WaitForMultipleObjects(2,evhandle,TRUE,INFINITE);
DeleteCriticalSection(&cs);
wsprintf(szBuffer, "%d",total);
MessageBox(NULL,szBuffer,TEXT("total"),0);
return 0;
}
運行情況;
程序有兩個線程;每個線程都要操作變量total;total初始值爲100;線程,是同時執行的;
線程1先進入臨界區,操作total,此時線程2不能操作total;線程1對total減去90,提示"You get $90";然後total的值爲10;
然後線程1退出臨界區,線程2進入臨界區,線程2開始操作total;
此時 10-20,小於0;所以線程2提示 "You haven't right to withdraw so much money";
線程2執行完,退出臨界區;
程序繼續執行,提示最終的total值:10;
工程;