C++的CreateEvent
一、事件是很常用的多线程同步互斥机制
函数原型如下所示,一共四个参数:
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES结构指针,可为NULLBOOL bManualReset, // 手动/自动// TRUE:表示手动,在WaitForSingleObject后必须手动调用ResetEvent清除信号// FALSE:表示自动,在WaitForSingleObject后,系统自动清除事件信号BOOL bInitialState, //初始状态,FALSE为无信号,TRUE为有信号LPCTSTR lpName //事件的名称);
SetEvent是用来设定事件为有信号,ResetEvent设置事件为无信号。
那事件有信号和无信号到底有什么用,又是怎么用的呢?可以想象以下这样的场景,比如一群人在等候就餐,服务员喊道:38号(有信号)。那38号顾客就可以去就餐,对于那些没被叫道号(无信号)则需继续排队。同样如此,对于多线程只有当该线程有信号时,才能获取CPU事件进而执行相关操作;如果没有信号,则只能继续排队等待(处于阻塞状态)
那线程是怎么获取这时候是否有信号呢?通过WaitForSingleObject函数,下面看函数介绍
This function returns when the specified object is in the signaled state or when the time-out interval elapses.DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); 第一个参数指明对象句柄,我们可以把创建的事件句柄赋予它第二个参数表明wait时间。我就等你三年,三年等不到就结婚了....最重要的是通过返回值来做进一步操作,该函数主要有几个返回值:WAIT_ABANDONED——说明句柄代表的对象是个互斥对象,并且正在被其它线程占用。意思就是说哥们你得等等,我还没完事呢WAIT_OBJECT_0——说明句柄对象处于有信号状态WAIT_TIMEOUT——在指定的时间内得不到答复(等待超时)且句柄对象处于无信号状态。意思就是你是个好人,今生别等了,下辈子见吧
二、下面是使用演示
实例一
CreateEvent(NULL, TRUE, TRUE, NULL)——初始状态为有信号,且需手动重置才能为无信号的事件
HANDLE g_hEvent;
DWORD WINAPI procFunc1(LPVOID lpParam)
{cout << "start thread1" << endl;if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0){cout << "thread1 is working..." << endl;}cout << "leve thread1..." << endl;return 0;
}DWORD WINAPI procFunc2(LPVOID lpParam)
{cout << "start thread2" << endl;if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0)//有信号,继续执行{cout << "thread2 is working..." << endl;}cout << "leve thread2..." << endl;return 0;
}int main()
{g_hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc1, NULL, 0, NULL);Sleep(500);CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc2, NULL, 0, NULL);return 0
}

可以看到线程1和线程2都完整执行了。因为创建的事件是需手动Reset才会无信号的,所以执行完线程1后事件仍处于有信号状态,所以线程2才能被继续执行
实例二、
再看另一个场景:CreateEvent(NULL, FALSE, TRUE, NULL)——初始状态为有信号且无需手动重置才能为无信号的事件
代码与上几乎相同,区别在与创建事件时参数

输出

可以看到线程1完整执行了,但是由于信号在执行完线程1后被自动重置为无信号,所以线程2中的逻辑没被执行
实例三、使用SetEvent,ResetEvent
HANDLE g_hEvent = NULL;
DWORD WINAPI procFunc1(LPVOID lpParam)
{cout << "start thread1" << endl;if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0){cout << "thread1 is working..." << endl;}cout << "leve thread1..." << endl;ResetEvent(g_hEvent);//重置事件为无信号return 0;
}DWORD WINAPI procFunc2(LPVOID lpParam)
{cout << "start thread2" << endl;if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0)//因为没信号,所以不会执行{cout << "thread2 is working..." << endl;}cout << "leve thread2..." << endl;return 0;
}int main()
{g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);SetEvent(g_hEvent);CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc1, NULL, 0, NULL);Sleep(500);CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc2, NULL, 0, NULL);
}
参考:
https://blog.csdn.net/u013407012/article/details/78585431
https://blog.csdn.net/u011394598/article/details/82981399
https://blog.csdn.net/weixin_43935710/article/details/103715571?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
