第19節(1 / 2)

{

cout << "only one instance can run!" << endl;

return;

}

}

HANDLE hThread1;

HANDLE hThread2;

hThread1 = CreateThread(NULL, 0, Thread1Proc, NULL, 0, NULL);

hThread2 = CreateThread(NULL, 0, Thread2Proc, NULL, 0, NULL);

CloseHandle(hThread1);//釋放線程句柄

CloseHandle(hThread2);

Sleep(4000);

CloseHandle(g_hEvent);//注意最後釋放事件對象句柄,在MFC中在類的析構函數中完成

}

DWORD WINAPI Thread1Proc(

LPVOID lpParameter // thread data

)

{

//其中的SetEvent函數應該在兩個判斷中都調用,以防止因條件不滿足而造成對象不能被設置為有信息狀態

while(TRUE){

WaitForSingleObject(g_hEvent, INFINITE);//無限期等待事件對象為有信號狀態

if (tickets > 0)//進入保護代碼

{

cout << "Thread1 is selling tickets : " << tickets-- << endl;

SetEvent(g_hEvent);

}

Else//如果票已經售完,退出循環

{

break;

SetEvent(g_hEvent);

}

}

return 0;

}

DWORD WINAPI Thread2Proc(

LPVOID lpParameter // thread data

)

{

while(TRUE){

WaitForSingleObject(g_hEvent, INFINITE);

//等待事件對象,如果對象為有信號狀態,可以請求該對象資源,並將其設置為無信息狀態

if (tickets > 0)

{

cout << "Thread2 is selling tickets : " << tickets-- << endl;

SetEvent(g_hEvent);

}

else

{

break;

SetEvent(g_hEvent);//設置事件對象為有信號狀態

}

}

return 0;

}

綜上:為實現線程間的同步,不應該使用人工重置的事件對象,而應該使用自動重置的事件對象

2. 關鍵代碼段(臨界區)

工作在用戶方式下,它是指一個小代碼段,在代碼能夠執行前,它必須獨占對某些資源的訪問權,通常把多線程訪問同一種資源的那部分代碼當作關鍵代碼段.

VOID InitializeCriticalSection(//初始化代碼段

LPCRITICAL_SECTION lpCriticalSection //[out] critical section,使用之前要構造

);

VOID EnterCriticalSection(//進入關鍵代碼段(臨界區)

LPCRITICAL_SECTION lpCriticalSection // critical section

);