一个自动重置事件的对象,WaitForSingleObject在等待成功以后会把事件对象设置为未触发状态(马上调用ResetEvent()函数),而手动设置事件对象不会有这个副作用。
#include <iostream> #include <process.h> #include <windows.h> #include <string> using std::cout; using std::endl; using std::string; const int num=10; int count; HANDLE ThreadEvent; unsigned __stdcall ThreadFun(void* par); int main() { //创建内核事件对象(自动重置,未激活状态) ThreadEvent=CreateEvent(NULL,FALSE,FALSE,NULL); HANDLE handles[num]; for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); WaitForSingleObject(ThreadEvent,INFINITE); //自动激活状态的事件,WaitForSingleObject带来的副作用就是会自己调用ResetEvent()将事件设置为未激活 } for(int i=0;i<num;++i) CloseHandle(handles[i]); CloseHandle(ThreadEvent);//关闭内核事件对象 system("PAUSE"); return 0; } unsigned __stdcall ThreadFun(void* par) { cout<<"count:"<<++count<<endl; SetEvent(ThreadEvent);//设置事件为激活状态 return 0; }
把事件对象设置为手动重置,就需要我们手动重置事件状态。
int main() { //创建内核事件对象(手动重置,未激活状态) ThreadEvent=CreateEvent(NULL,TRUE,FALSE,NULL); HANDLE handles[num]; for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); WaitForSingleObject(ThreadEvent,INFINITE); //手动激活的事件,WaitForSingleObject不会重置事件为未激活。 ResetEvent(ThreadEvent);//手动重置事件对象为未激活状态 } for(int i=0;i<num;++i) CloseHandle(handles[i]); CloseHandle(ThreadEvent);//关闭内核事件对象 system("PAUSE"); return 0; }
上面代码内核事件对象为手动重置,所以在WaitForSingleObject以后需要手动调用ResetEvent(),如果把ResetEvent(ThreadEvent);注释掉,那么所以等待线程都会被触发,导致同步失败。
for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); WaitForSingleObject(ThreadEvent,INFINITE); //手动激活的事件,WaitForSingleObject不会重置事件为未激活。 //ResetEvent(ThreadEvent);//后面的线程都会很顺利的执行,事件对象一直为激活状态 }
线程执行同步失败,输出混乱,可以将num变量设置大点,这样更加容易出现混乱输出。
本文版权归kennyMc和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。