1. 程式人生 > >C++中Event使用

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      :表示等待物件控制代碼是一個無效控制代碼。

程式碼示例:

功能:用主執行緒來等待子執行緒的執行結束

  1. HANDLE hEvent;  
  2. int num=1;  
  3. DWORD WINAPI _threadProc(LPVOID lpParam)  
  4. {  
  5.     for(int i=0; i<10000; i++)  
  6.     {  
  7.         for(int j=0; j<10000; j++)  
  8.             ;  
  9.     }  
  10.     num=10;  
  11.     SetEvent(hEvent);  
  12.     return 0;  
  13. }  
  14. void main()  
  15. {  
  16.     //手動復位,初始時無訊號
  17.     hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);  
  18.     if(hEvent==NULL)  
  19.     {     
  20.         printf("hEvent is null\n");  
  21.         return;  
  22.     }  
  23.     HANDLE hThread=CreateThread(NULL, 0, _threadProc, NULL, 0, NULL);  
  24.     DWORD dwRet=WaitForSingleObject(hEvent, INFINITE);  
  25.     if(dwRet==WAIT_ABANDONED)  
  26.         printf("WAIT_ABANDONED\n");  
  27.     elseif(dwRet==WAIT_TIMEOUT)  
  28.         printf("WAIT_TIMEOUT\n");  
  29.     elseif(dwRet==WAIT_OBJECT_0)  
  30.         printf("有訊號狀態\n");  
  31.     elseif(dwRet==WAIT_FAILED)  
  32.         printf("WAIT_FAILED\n");  
  33.     printf("sub thread run out, num is %d\n", num);