前面三章我们介绍了多线程同步处理方法是创建互斥对象来实现多线程同步运行。这章我们讲解如何运用事件对象来处理线程同步:
事件对象也是属于内核对象,其包含三个成员:1.使用计数;2.用于指明该事件是一个自动重置的事件还是一个人工重置的事件的布尔值;3.用于指明该事件处于已通知状态还是未通知状态的布尔值。
事件对象有两种不同的类型:人工重置的事件对象和自动重置的事件对象。
事件对象的创建函数为HANDLE CreateEvent,-------用于创建或者打开一个命名的或匿名的事件对象。
1 CreateEvent( 2 LPSECURITY_ATTRIBUTES lpEventAttributes, 3 BOOL bManualReset, 4 BOOL bInitialState, 5 LPCWSTR lpName 6 );
参数说明:
- 安全属性,如果为NULL,则使用默认的安全性;
- 人工重置,如果为true,则表示该函数将创建一个人工重置事件对象;否则为自动重置对象;
- 事件对象状态初始化,如果为true,表示该事件对象初始值是有信号状态;否则是无信号状态;
- 事件对象名称,如果为NULL,表示创建一个匿名的事件对象。
重置事件对象状态函数: BOOL ResetEvent(HANDLE hEvent);
设置事件对象状态函数: BOOL SetEvent(HANDLE hEvent);
同样,下面举例说明其如何实现之前多线程同步的例程,代码如下:
1 #include<windows.h> 2 #include<iostream.h> 3 4 DWORD WINAPI Fun1Proc(LPVOID lpParameter); 5 DWORD WINAPI Fun2Proc(LPVOID lpParameter); 6 7 int tick=100; 8 //HANDLE hMutex; 9 HANDLE g_hEvent; 10 void main() 11 { 12 HANDLE hThread1; 13 HANDLE hThread2; 14 g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL); 15 SetEvent(g_hEvent); 16 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); 17 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); 18 CloseHandle(hThread1); 19 CloseHandle(hThread2); 20 Sleep(4000); 21 CloseHandle(g_hEvent); 22 } 23 //thread function 24 DWORD WINAPI Fun1Proc(LPVOID lpParameter) 25 { 26 WaitForSingleObject(g_hEvent,INFINITE); 27 while(true) 28 { 29 if(tick>0) 30 { 31 Sleep(1); 32 cout<<"Thread1 sell tick:"<<tick--<<endl; 33 SetEvent(g_hEvent); 34 } 35 else 36 { 37 SetEvent(g_hEvent); 38 break; 39 } 40 } 41 return 0; 42 } 43 //thread function 44 DWORD WINAPI Fun2Proc(LPVOID lpParameter) 45 { 46 WaitForSingleObject(g_hEvent,INFINITE); 47 while(true) 48 { 49 if(tick>0) 50 { 51 Sleep(1); 52 cout<<"Thread2 sell tick:"<<tick--<<endl; 53 SetEvent(g_hEvent); 54 } 55 else 56 { 57 SetEvent(g_hEvent); 58 break; 59 } 60 } 61 return 0; 62 }
创建一个自动重置的事件对象,之后设置事件对象为有信号状态。
创建线程延时,接收事件对象操作;
简结:当一个自动重置的事件对象得到通知时,等待该事件对象的线程中只有一个线程变为可调度线程,同时操作系统会将该事件对象设置无信号状态,这样当对所保护的代码执行完成后,需要重置该事件对象为有信号状态。
当一个人工重置事件对象在一个线程中得到该事件对象之后,系统不会设置该事件对象的为无信号状态,需要用户手动调用重置函数(ResetEvent)函数。否则该事件对象将会一直处于有信号状态。
End.
谢谢.