C++中Event使用
之前執行緒同步用互斥鎖Mutex或使用者模式的CriticalSection等來進行同步,而且使用效果一直很好,直到最近遇到新問題,朋友推薦用事件去處理。但是對事件瞭解比較少,所以摘了篇文章看,另外自己做了下試驗(所以程式碼不是轉的哦)。
概念:
事件是用來同步地位不相等的執行緒的,事件可以用來使一個執行緒完成一件事情,然後另外的執行緒完成剩下的事情。
事件的使用很靈活,自動事件的激發態是由人工來控制的(超級重要,尤其是在需要精確掌控是否處於有訊號狀態的時候),而Mutex在釋放(releaseMetux)後就一直處於激發態,直到執行緒WaitForSingleObject。事件可以用來控制經典的讀寫模型和生產者和消費者模型。相應的方式為,生成者等待消費者的消費,再消費者消費完後通知生產者進行生產。
Mutex是排他的佔有資源,一般用於地位相等的執行緒進行同步。每個執行緒都可以排他的訪問一個資源或程式碼段,不存在哪個執行緒對資源訪問存在優先次序。一個執行緒只能在Mutex處於激發態的時候訪問被保護的資源或程式碼段,執行緒可以通過WaitForSingelObject來等待Mutex,在訪問資源完成之後,ReleaseMutex釋放Mutex,此時Mutex處於激發態。
注意:對控制代碼使用WaitForSIngleObject()之後的副作用(控制代碼狀態的自動變化)
Mutex具有成功等待的副作用,在用WaitForSingleObject()等待到Mutex後,Mutex自動變為無訊號狀態,直到呼叫ReleaseMutex()使Mutex變為有訊號狀態為止;
自動事件也具有成功等待的副作用;
手動事件沒有,必須呼叫ResetEvent()使手動事件變為未激發態;
程序和執行緒也沒有成功等待的副作用。當執行緒或者程序函式返回時,執行緒核心物件變為激發態,但WaitForSingleObject並沒有使執行緒或者程序的核心物件變為未激發態。
總之,事件一般用於控制執行緒的先後順序,而Mutex一般用於排他的訪問資源。
Event的使用:
首先建立事件:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全屬性
BOOL bManualReset, // 復位方式,1為手動復位,0為自動復位
BOOL bInitialState, // 初始狀態,0為不可用狀態即無訊號,1為可用狀態即有訊號
LPCTSTR lpName // 物件名稱
);
SetEvent()設定事件為有訊號;ResetEvent()設定事件為無訊號。
WaitForSingleObject()來等待Event變為有訊號:
DWORD WaitForSignalObject(HANDLE hObject, DWORD dwMilliseconds);
返回值有以下幾種:
WAIT_OBJECT_0 :表示等待物件已經變為有訊號狀態,如果設定為自動復位,還會把此訊號再次變為無訊號狀態。
WAIT_TIMEOUT :表示等待超時
WAIT_FAILED :表示等待物件控制代碼是一個無效控制代碼。
程式碼示例:
功能:用主執行緒來等待子執行緒的執行結束
- HANDLE hEvent;
- int num=1;
- DWORD WINAPI _threadProc(LPVOID lpParam)
- {
- for(int i=0; i<10000; i++)
- {
- for(int j=0; j<10000; j++)
- ;
- }
- num=10;
- SetEvent(hEvent);
- return 0;
- }
- void main()
- {
- //手動復位,初始時無訊號
- hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
- if(hEvent==NULL)
- {
- printf("hEvent is null\n");
- return;
- }
- HANDLE hThread=CreateThread(NULL, 0, _threadProc, NULL, 0, NULL);
- DWORD dwRet=WaitForSingleObject(hEvent, INFINITE);
- if(dwRet==WAIT_ABANDONED)
- printf("WAIT_ABANDONED\n");
- elseif(dwRet==WAIT_TIMEOUT)
- printf("WAIT_TIMEOUT\n");
- elseif(dwRet==WAIT_OBJECT_0)
- printf("有訊號狀態\n");
- elseif(dwRet==WAIT_FAILED)
- printf("WAIT_FAILED\n");
- printf("sub thread run out, num is %d\n", num);