事件是一个内核事件,内核事件是什么呢,我理解也不深入也不好说,暂且理解为一个内核维护的数据类型吧通过内核事件同步主要
的方法是对事件的信号有和无来进行同步。
比如当我们一个线程进入一段临界代码(独占代码段,不可多个线程同时访问)那么这时候我们将事件对象设置为无信号状态。那么另外
一个线程便会在等待这样一个事件对象,直到该事件对象执行完临界代码,然后将事件对象设为有信号状态,此时便可以该线程便可进
入临界代码段。
利用事件对象进行同步主要有以下几个API;
该函数用于创建一个匿名的事件对象,返回值为创建的事件对象
第一个参数为安全属性,当为NULL,设置为默认安全属性
第二个参数为手动或自动改变时间对象的信号状态。TRUE为手动。FALSE为自动
第三个参数为事件对象的初始化状态,TRUE为初始有信号状态,FALSE为初始无信号状态
第四个是事件对象的名称,NULL说明未匿名事件对象
一般情况下,我们选择创建一个默认安全属性,手工置位,初始为有信号状态,未命名的事件对象
该函数将事件对象置为有信号状态,成功则返回非零值,失败则返回零值。
该函数将事件对象置为无信号状态,成功则返回非零值,失败则返回零值
关闭事件对象,在程序结束之前。
该函数用于等待事件对象是否为有信号状态,如果为信号状态则返回,否则一直阻塞。其传入连个参数一个是事件对象,一个是超时
间隔。当第二个参数为INFINITE的时候该函数将一直阻塞知道事件被置为有信号状态。
我们还是以典型的卖票的例子来进行测试,代码实现如下:
1 #include <windows.h> 2 #include <stdio.h> 3 4 static int number=10; 5 HANDLE SigHand; 6 7 DWORD WINAPI ThreadOne(LPVOID lpParameter) 8 { 9 printf("窗口1售票开始: "); 10 while(1) 11 { 12 WaitForSingleObject(SigHand,INFINITE); 13 ResetEvent(SigHand); 14 if(number>0) 15 { 16 printf("窗口1售出第%d张票... ",number); 17 number--; 18 Sleep(1000); 19 } 20 SetEvent(SigHand); 21 Sleep(100); 22 } 23 return 0; 24 } 25 DWORD WINAPI ThreadTwo(LPVOID lpParameter) 26 { 27 printf("窗口2售票开始: "); 28 while(1) 29 { 30 WaitForSingleObject(SigHand,INFINITE); 31 ResetEvent(SigHand); 32 if(number>0) 33 { 34 printf("窗口2售出第%d张票... ",number); 35 Sleep(1000); 36 number--; 37 } 38 SetEvent(SigHand); 39 Sleep(100); 40 } 41 return 0; 42 } 43 44 45 int main() 46 { 47 HANDLE HOne,HTwo; 48 49 printf("***********************vpoet****************** "); 50 HOne=CreateThread(NULL,0,ThreadOne,NULL,0,NULL); 51 HTwo=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL); 52 SigHand=CreateEvent(NULL,TRUE,TRUE,NULL); 53 CloseHandle(HOne); 54 CloseHandle(HTwo); 55 while(TRUE) 56 { 57 if(number==0) 58 { 59 printf("不好意思,票卖完了! "); 60 CloseHandle(SigHand); 61 return 0; 62 } 63 else 64 { 65 continue; 66 } 67 } 68 69 return 0; 70 }
运行截图: