5.事件
在之前的課程里面講過,線程在進(jìn)入臨界區(qū)之前會(huì)調(diào)用WaitForSingleObject或者WaitForMultipleOobjects,此時(shí)如果有信號(hào),線程會(huì)從函數(shù)中退出并進(jìn)入臨界區(qū),如果沒有信號(hào)那么線程將自己掛入等待鏈表,然后將自己掛入等待網(wǎng),最后切換線程。
其他線程在適當(dāng)?shù)臅r(shí)候,調(diào)用方法修改被等待對(duì)象的 SignalState 為有信號(hào)(不同的等待對(duì)象,會(huì)調(diào)用不同的函數(shù)),并將等待該對(duì)象的其他線程從等待鏈表中摘掉,這樣,當(dāng)前線程便會(huì)在 WaitForSingleObject 或者 WaitForMultipleObjects 恢復(fù)執(zhí)行(在哪切換在哪開始執(zhí)行),如果符合喚醒條件,此時(shí)會(huì)修改 SignalState 的值,并將自己從等待網(wǎng)上摘下來,此時(shí)的線程才是真正的喚醒。
被等待對(duì)象不同,主要在2個(gè)點(diǎn)上會(huì)有差異:
創(chuàng)建事件對(duì)象:信號(hào)
測試代碼:
HANDLE g_hEvent;VOID WINAPI ThreadProc1(LPVOID text) {::WaitForSingleObject(g_hEvent, INFINITE);printf("ThreadProc1函數(shù)執(zhí)行...\n"); }VOID WINAPI ThreadProc2(LPVOID text) {::WaitForSingleObject(g_hEvent, INFINITE);printf("ThreadProc2函數(shù)執(zhí)行...\n"); }VOID WINAPI ThreadProc3(LPVOID text) {::WaitForSingleObject(g_hEvent, INFINITE);printf("ThreadProc3函數(shù)執(zhí)行...\n"); }int main() {//默認(rèn)安全屬性 對(duì)象類型 初始狀態(tài) 名字g_hEvent = ::CreateEvent(NULL, false, FALSE, NULL);HANDLE hThread[3];//創(chuàng)建3個(gè)線程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);//設(shè)置事件為已通知SetEvent(g_hEvent);//等待線程結(jié)束 銷毀內(nèi)核對(duì)象WaitForMultipleObjects(3, hThread, TRUE, INFINITE);CloseHandle(hThread[0]);CloseHandle(hThread[1]);CloseHandle(hThread[2]);CloseHandle(g_hEvent);getchar();return 0; } //參數(shù)1:默認(rèn)安全屬性 //參數(shù)2:對(duì)象類型 //參數(shù)3:初始化的事件狀態(tài) //參數(shù)4:名稱 CreateEvent(NULL, TRUE, FALSE, NULL);//如果參數(shù)2為true 通知類型對(duì)象,false 事件同步對(duì)象 //如果參數(shù)3為false未通知,true已通知_DISPATCHER_HEADER +0x000 Type //對(duì)應(yīng)上面第2個(gè)參數(shù) +0x001 Absolute +0x002 Size +0x003 Inserted +0x004 SignalState //對(duì)應(yīng)上面第3個(gè)參數(shù) +0x008 WaitListHeadSetEvent函數(shù)分析
SetEvent對(duì)應(yīng)的內(nèi)核函數(shù): KeSetEvent
還是這個(gè)偽代碼
while(true)//每次線程被其他線程喚醒,都要進(jìn)入這個(gè)循環(huán){if(符合激活條件)//1超時(shí) 2等待對(duì)象SignalState > 0{//1修改SignalState //2退出循環(huán)}else//SignalState不大于0 也沒超時(shí){if(第一次執(zhí)行){//將當(dāng)前線程的等待塊掛到等待對(duì)象的鏈表 (WaitListHead) 中;//將自己掛入等待隊(duì)列(KiaitListHead)//切換線程...再次獲得CPU時(shí),從這里開始執(zhí)行}}} 1)線程將自己+5c位置清0 2)釋放_(tái)KWAIT_BLOCK所占內(nèi)存如果事件類型為TRUE,跳到這
總結(jié)
- 上一篇: 4.WaitForSingleObjec
- 下一篇: 6.信号量