天天看点

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 插件

继续阅读