事件内核对象
包括人工重置的事件和自动重置的事件。
人工重置事件:
当人工重置事件得到通知时,等待该事件的所有线程成为可调度线程;它没有成功等待的副作用
自动重置事件:
当自动重置事件得到通知时,等待该事件的线程中只有一个变为可调度线程。其成功等待的副作用是该事件对象自动重置为未通知状态。
事件内核对象通过createevent创建,初始可以是通知或未通知状态,setevent将事件改为已通知状态,resetevent将事件设为未通知状态。
当一个线程执行初始化操作,然后通知另一个线程执行剩余的操作时,经常使用人工事件对象。另外如果一个写线程,多个读线程,可以让写线程完成写操作时通过人工事件通知读线程读取数据。而自动事件对象则可以用于保护资源在同一时间只有一个线程可以访问,因为它保证只有一个线程激活。
示例1:人工重置事件
// 使用人工重置事件,线程间同步
#include <process.h>
#include <windows.h>
#include <iostream>
using namespace std;
int Ticket = 100;
HANDLE hdl = nullptr;
unsigned int __stdcall fun1(LPVOID lpParameter)
{
while (Ticket > 0)
{
WaitForSingleObject(hdl, INFINITE);//等待事件已通知状态
ResetEvent(hdl);//等到信号后,立刻将事件设置为未通知状态
Sleep(1);//这里sleep一下,确保其他线程处于等待状态
printf("fun1 %d\n",Ticket--);
SetEvent(hdl);//执行完毕后,立刻将事件设置为已通知状态
Sleep(1);//这里sleep一下,确保该线程下一次不会抢到执行权。
}
return 0;
}
unsigned int __stdcall fun2(LPVOID lpParameter)
{
while (Ticket > 0)
{
WaitForSingleObject(hdl, INFINITE);//等待事件已通知状态
ResetEvent(hdl);//等到信号后,立刻将事件设置为未通知状态
Sleep(1);
printf("fun2 %d\n", Ticket--);
SetEvent(hdl);//执行完毕后,立刻将事件设置为已通知状态
Sleep(1);//这里sleep一下,确保该线程下一次不会抢到执行权。
}
return 0;
}
int main()
{
// 创建事件:人工重置,初始为未通知状态
hdl = CreateEvent(nullptr, TRUE, FALSE, NULL);
SetEvent(hdl);//设置事件有信号状态
// 创建线程
HANDLE hThread[2] = { 0 };
hThread[0] = (HANDLE)_beginthreadex(nullptr, 0, fun1, nullptr, 0, nullptr);
hThread[1] = (HANDLE)_beginthreadex(nullptr, 0, fun2, nullptr, 0, nullptr);
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
getchar();
CloseHandle(hdl);
return 0;
}
执行结果:截取了部分,可以看到线程1和线程2交替执行。
示例2:自动重置事件
// 使用自动重置事件,线程间同步
#include <process.h>
#include <windows.h>
#include <iostream>
using namespace std;
int Ticket = 100;
HANDLE hdl = nullptr;
unsigned int __stdcall fun1(LPVOID lpParameter)
{
while (Ticket > 0)
{
WaitForSingleObject(hdl, INFINITE);//等待事件已通知状态
Sleep(1);//这里sleep一下,确保其他线程处于等待状态,此时事件已经自动重置为未通知状态
printf("fun1 %d\n",Ticket--);
SetEvent(hdl);//执行完毕后,立刻将事件设置为已通知状态
Sleep(1);//这里sleep一下,确保该线程下一次不会抢到执行权。
}
return 0;
}
unsigned int __stdcall fun2(LPVOID lpParameter)
{
while (Ticket > 0)
{
WaitForSingleObject(hdl, INFINITE);//等待事件已通知状态
Sleep(1);
printf("fun2 %d\n", Ticket--);
SetEvent(hdl);//执行完毕后,立刻将事件设置为已通知状态
Sleep(1);//这里sleep一下,确保该线程下一次不会抢到执行权。
}
return 0;
}
int main()
{
// 创建事件:人工重置,初始为未通知状态
hdl = CreateEvent(nullptr, FALSE, FALSE, NULL);
SetEvent(hdl);//设置事件有信号状态
// 创建线程
HANDLE hThread[2] = { 0 };
hThread[0] = (HANDLE)_beginthreadex(nullptr, 0, fun1, nullptr, 0, nullptr);
hThread[1] = (HANDLE)_beginthreadex(nullptr, 0, fun2, nullptr, 0, nullptr);
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
getchar();
CloseHandle(hdl);
return 0;
}
运行结果: