天天看點

windows多線程同步--事件

事件是核心對象,多用于線程間通信,可以跨程序同步

CreateEvent 函數功能:建立事件 函數原型: HANDLECreateEvent( LPSECURITY_ATTRIBUTESlpEventAttributes, BOOLbManualReset, BOOLbInitialState, LPCTSTRlpName ); 第一個參數:表示安全控制,一般直接傳入NULL。 第二個參數:确定事件是手動置位還是自動置位,傳入TRUE表示手動置位,傳入FALSE表示自動置位。如果為自動置位,則對該事件調用WaitForSingleObject()後會自動調用ResetEvent()使事件變成未觸發狀态。打個小小比方,手動置位事件相當于教室門,教室門一旦打開(被觸發),是以有人都可以進入直到老師去關上教室門(事件變成未觸發)。自動置位事件就相當于醫院裡拍X光的房間門,門打開後隻能進入一個人,這個人進去後會将門關上,其它人不能進入除非門重新被打開(事件重新被觸發)。 第三個參數:表示事件的初始狀态,傳入TRUR表示已觸發。 第四個參數:表示事件的名稱,傳入NULL表示匿名事件。 傳回值:事件的句柄
OpenEvent 函數功能:根據名稱獲得一個事件句柄。 HANDLEOpenEvent( DWORDdwDesiredAccess, BOOLbInheritHandle, LPCTSTRlpName     //名稱 函數說明: 第一個參數:表示通路權限,對事件一般傳入EVENT_ALL_ACCESS。詳細解釋可以檢視MSDN文檔。 第二個參數:表示事件句柄繼承性,一般傳入TRUE即可。 第三個參數:表示名稱,不同程序中的各線程可以通過名稱來確定它們通路同一個事件。 傳回值:傳回事件的句柄
SetEvent 函數功能:觸發事件 函數原型:BOOLSetEvent(HANDLEhEvent); 函數說明:每次觸發後,必有一個或多個處于等待狀态下的線程變成可排程狀态。
ResetEvent 函數功能:将事件設為末觸發 函數原型:BOOLResetEvent(HANDLEhEvent);

下面從一個例子說明:假設有三個線程都需要使用列印機,我們可以使用互斥量來控制,這樣就可以保證每次隻有一個線程在使用列印機

使用自動置位,那麼在調用WaitForSingleObject()後會自動調用ResetEvent()使事件變為未觸發狀态,為了使後面的線程能夠繼續列印,需要線上程函數的結尾調用SetEvent來觸發事件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

<code>#include&lt;string&gt;</code>

<code> </code><code>#include&lt;iostream&gt;</code>

<code> </code><code>#include&lt;process.h&gt;</code>

<code> </code><code>#include&lt;windows.h&gt;</code>

<code> </code><code>using</code> <code>namespace</code> <code>std;</code>

<code> </code><code>//聲明事件句柄</code>

<code> </code><code>HANDLE</code> <code>hev;</code>

<code>//線程綁定的函數傳回值和參數是确定的,而且一定要__stdcall</code>

<code>unsigned __stdcall threadFun(</code><code>void</code> <code>*param)</code>

<code>{</code>

<code>    </code><code>WaitForSingleObject(hev, INFINITE);</code><code>//等待事件被觸發</code>

<code>    </code><code>for</code><code>(</code><code>int</code> <code>i = 0; i &lt; 10; i++)</code>

<code>        </code><code>cout&lt;&lt;*(string *)(param)&lt;&lt;</code><code>" "</code><code>;</code>

<code>    </code><code>cout&lt;&lt;endl;</code>

<code>    </code><code>SetEvent(hev);</code><code>//設定事件為觸發狀态,使後面的線程可以列印</code>

<code>    </code><code>return</code> <code>1;</code>

<code>}</code>

<code>int</code> <code>main()</code>

<code>    </code><code>//建立一個未被觸發的事件,事件是自動置位的</code>

<code>    </code><code>hev = CreateEvent(NULL, FALSE, FALSE, NULL);</code>

<code>    </code><code>SetEvent(hev);</code><code>// 觸發事件,使線程可以列印</code>

<code>    </code><code>HANDLE</code> <code>hth1, hth2, hth3;</code>

<code>    </code><code>string s1 =</code><code>"first"</code><code>, s2 =</code><code>"second"</code><code>, s3 =</code><code>"third"</code><code>;</code>

<code>    </code><code>//建立線程</code>

<code>    </code><code>hth1 = (</code><code>HANDLE</code><code>)_beginthreadex(NULL, 0, threadFun, &amp;s1, 0, NULL);</code>

<code>    </code><code>hth2 = (</code><code>HANDLE</code><code>)_beginthreadex(NULL, 0, threadFun, &amp;s2, 0, NULL);</code>

<code>    </code><code>hth3 = (</code><code>HANDLE</code><code>)_beginthreadex(NULL, 0, threadFun, &amp;s3, 0, NULL);</code>

<code>    </code><code>//等待子線程結束</code>

<code>    </code><code>WaitForSingleObject(hth1, INFINITE);</code>

<code>    </code><code>WaitForSingleObject(hth2, INFINITE);</code>

<code>    </code><code>WaitForSingleObject(hth3, INFINITE);</code>

<code>    </code><code>//一定要記得關閉線程句柄</code>

<code>    </code><code>CloseHandle(hth1);</code>

<code>    </code><code>CloseHandle(hth2);</code>

<code>    </code><code>CloseHandle(hth3);</code>

<code>    </code><code>//千萬别忘了删除事件</code>

<code>    </code><code>CloseHandle(hev);</code>

windows多線程同步--事件

使用手動置位,調用WaitForSingleObject()後事件就一直是觸發狀态,線程可以任意的列印

<code>    </code><code>//SetEvent(hev);//設定事件為觸發狀态,使後面的線程可以列印</code>

<code>    </code><code>//建立一個未被觸發的事件,事件是手動置位的</code>

<code>    </code><code>hev = CreateEvent(NULL, TRUE, FALSE, NULL);</code>

windows多線程同步--事件

再通過下面的例子來看看時間有沒有所有權屬性:編寫一個程式,開啟3個線程,這3個線程的ID分别為A、B、C,每個線程将自己的ID在螢幕上列印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

<code> </code><code>//聲明3個事件句柄</code>

<code>HANDLE</code>  <code>hev1, hev2, hev3;</code>

<code>unsigned __stdcall threadFunA(</code><code>void</code> <code>*)</code>

<code>    </code><code>for</code><code>(</code><code>int</code> <code>i = 0; i &lt; 10; i++){</code>

<code>        </code><code>WaitForSingleObject(hev1, INFINITE);</code><code>//等待事件1</code>

<code>        </code><code>cout&lt;&lt;</code><code>"A"</code><code>;</code>

<code>        </code><code>SetEvent(hev2);</code><code>//觸發事件2</code>

<code>    </code><code>}</code>

<code>unsigned __stdcall threadFunB(</code><code>void</code> <code>*)</code>

<code>        </code><code>WaitForSingleObject(hev2, INFINITE);</code><code>//等待事件2</code>

<code>        </code><code>cout&lt;&lt;</code><code>"B"</code><code>;</code>

<code>        </code><code>SetEvent(hev3);</code><code>//觸發事件3</code>

<code>    </code><code>return</code> <code>2;</code>

<code>unsigned __stdcall threadFunC(</code><code>void</code> <code>*)</code>

<code>        </code><code>WaitForSingleObject(hev3, INFINITE);</code><code>//等待事件3</code>

<code>        </code><code>cout&lt;&lt;</code><code>"C"</code><code>;</code>

<code>        </code><code>SetEvent(hev1);</code><code>//觸發事件1</code>

<code>    </code><code>return</code> <code>3;</code>

<code>    </code><code>hev1 = CreateEvent(NULL, FALSE, FALSE, NULL);</code>

<code>    </code><code>hev2 = CreateEvent(NULL, FALSE, FALSE, NULL);</code>

<code>    </code><code>hev3 = CreateEvent(NULL, FALSE, FALSE, NULL);</code>

<code>    </code><code>SetEvent(hev1);</code><code>//觸發事件1,從A開始列印</code>

<code>    </code><code>hth1 = (</code><code>HANDLE</code><code>)_beginthreadex(NULL, 0, threadFunA, NULL, 0, NULL);</code>

<code>    </code><code>hth2 = (</code><code>HANDLE</code><code>)_beginthreadex(NULL, 0, threadFunB, NULL, 0, NULL);</code>

<code>    </code><code>hth3 = (</code><code>HANDLE</code><code>)_beginthreadex(NULL, 0, threadFunC, NULL, 0, NULL);</code>

<code>    </code><code>//删除事件</code>

<code>    </code><code>CloseHandle(hev1);</code>

<code>    </code><code>CloseHandle(hev2);</code>

<code>    </code><code>CloseHandle(hev3);</code>

windows多線程同步--事件

由結果可知事件不具有所有權屬性,即某個線程擷取事件後,一定要等待事件再次被觸發。可參考本部落格其他文章中臨界區、互斥量、信号量的所有權屬性來了解。

本文轉自tenos部落格園部落格,原文連結:http://www.cnblogs.com/TenosDoIt/p/3601458.html,如需轉載請自行聯系原作者

下一篇: maven 插件

繼續閱讀