5.事件

在之前的课程里面讲过,线程在进入临界区之前会调用WaitForSingleObject或者WaitForMultipleOobjects,此时如果有信号,线程会从函数中退出并进入临界区,如果没有信号那么线程将自己挂入等待链表,然后将自己挂入等待网,最后切换线程

其他线程在适当的时候,调用方法修改被等待对象的 SignalState 为有信号(不同的等待对象,会调用不同的函数),并将等待该对象的其他线程从等待链表中摘掉,这样,当前线程便会在 WaitForSingleObject 或者 WaitForMultipleObjects 恢复执行(在哪切换在哪开始执行),如果符合唤醒条件,此时会修改 SignalState 的值,并将自己从等待网上摘下来,此时的线程才是真正的唤醒。

被等待对象不同,主要在2个点上会有差异:

创建事件对象:信号

测试代码:

HANDLE g_hEvent;

VOID WINAPI ThreadProc1(LPVOID text)
{
	::WaitForSingleObject(g_hEvent, INFINITE);
	printf("ThreadProc1函数执行...\n");
}

VOID WINAPI ThreadProc2(LPVOID text)
{
	::WaitForSingleObject(g_hEvent, INFINITE);
	printf("ThreadProc2函数执行...\n");
}

VOID WINAPI ThreadProc3(LPVOID text)
{
	::WaitForSingleObject(g_hEvent, INFINITE);
	printf("ThreadProc3函数执行...\n");
}

int main()
{
	//默认安全属性 对象类型 初始状态 名字
	g_hEvent = ::CreateEvent(NULL, false, FALSE, NULL);

	HANDLE hThread[3];

	//创建3个线程
	hThread[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0, NULL);
	hThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0, NULL);
	hThread[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc3, NULL, 0, NULL);

	//设置事件为已通知
	SetEvent(g_hEvent);

	//等待线程结束 销毁内核对象
	WaitForMultipleObjects(3, hThread, TRUE, INFINITE);
	CloseHandle(hThread[0]);
	CloseHandle(hThread[1]);
	CloseHandle(hThread[2]);
	CloseHandle(g_hEvent);

	getchar();
	return 0;
}
//参数1:默认安全属性
//参数2:对象类型
//参数3:初始化的事件状态
//参数4:名称
CreateEvent(NULL, TRUE, FALSE, NULL);

//如果参数2为true 通知类型对象,false 事件同步对象
//如果参数3为false未通知,true已通知
   
_DISPATCHER_HEADER 
+0x000 Type 		//对应上面第2个参数
+0x001 Absolute 
+0x002 Size 
+0x003 Inserted 
+0x004 SignalState 	//对应上面第3个参数
+0x008 WaitListHead

SetEvent函数分析

SetEvent对应的内核函数: KeSetEvent

  1. 修改信号值SignalState为1
  2. 判断对象类型
  3. 如果类型为通知类型对象(Type 0) 唤醒所有等待该状态的线程
  4. 如果类型为事件同步对象(Type 1) 从链表头找到第一个

还是这个伪代码

while(true)//每次线程被其他线程唤醒,都要进入这个循环
	{
		if(符合激活条件)//1超时 2等待对象SignalState > 0
		{
		//1修改SignalState 
		//2退出循环
		}
		else//SignalState不大于0 也没超时
		{
			if(第一次执行)
			{
				//将当前线程的等待块挂到等待对象的链表 (WaitListHead) 中;
				//将自己挂入等待队列(KiaitListHead)
				//切换线程...再次获得CPU时,从这里开始执行
			}
		}

	}
1)线程将自己+5c位置清0
2)释放_KWAIT_BLOCK所占内存

在这里插入图片描述

如果事件类型为TRUE,跳到这
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值