{
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
);