線程同步 等待函數 WaitForSingleObject WaitForMultipleObjects

0、思考

1、相關api

WaitForSingleObject
WaitForMultipleObjects
WaitForInputIdle(對父進程比較有用)
MsgWaitForMultipleObjects
MsgWaitForMultipleObjectsEx
WaitForDebugEvent
SignalObjectAndWait

2、寫在前面

等待函數:是一個線程自願進入等待狀態,直到指定的內核對象被觸發爲止。(內核對象:Event,Mutex,Semaphore,Process,Thread,
    Waitable timer,Job,Change notification,Console input,Memory resource notification)
等待成功所引起的副作用:對象的狀態發生了變化。(舉個栗子:假設線程等待一個自動重置事件對象,當事件對象被觸發時,函數返回WAIT_OBJECT_0
    之前事件變爲非觸發狀態)

3、api說明

// hHandle:要等待的內核對象
// dwMilliseconds:指定線程最多願意花多長時間來等待對象被觸發;(通常:INFINITE)
// WAIT_OBJECT_0:線程等待對象被觸發;WAIT_TIMEOUT:等待超時;WAIT_FAILED:(具體原因通過GetLastError知道)
WINBASEAPI
DWORD
WINAPI
WaitForSingleObject(
    __in HANDLE hHandle,
    __in DWORD dwMilliseconds
);

// 允許調用線程同時等待多個內核對象的觸發狀態
// nCount:希望函數檢查的內核對象的數量
// lpHandles:內核對象句柄的數組
// bWaitAll:指定內核對象中的一個被觸發爲止(false);直到指定內核對象中的全部被觸發爲止(true)
// dwMilliseconds:同WaitForSingleObject
// WAIT_OBJECT_0:如果bWaitAll爲ture,則表示所有對象都被觸發;如果bWaitAll爲false,返回[WAIT_OBJECT_0, WAIT_OBJECT_0 + nCount - 1]
    分別對應lpHandles數組中的某個內核對象
WINBASEAPI
DWORD
WINAPI
WaitForMultipleObjects(
    __in DWORD nCount,
    __in_ecount(nCount) CONST HANDLE *lpHandles,
    __in BOOL bWaitAll,
    __in DWORD dwMilliseconds
);

// 等待進程創建並初始化完畢(父進程能夠知道子進程已經初始化完畢的唯一方法就是等待子進程直到它不再處理任何輸入爲止;WM_KEY消息創建窗口耗時也可用此)
// hProcess:進程句柄。
// dwMilliseconds:等待時間。
WINUSERAPI
DWORD
WINAPI
WaitForInputIdle(
    __in HANDLE hProcess,
    __in DWORD dwMilliseconds
);

// 與WaitForMultipleObjects類似,不同之處於,不僅內核對象被觸發的時候調用線程變成可調度狀態,而且當窗口消息需要被派送到一個由調用線程創建的窗口是,它們也會變成可調度。創建窗口的線程和執行與用戶界面相關的任務的線程不應該使用WaitForMultipleObjects,因爲會妨礙線程對用戶在界面上的操作響應。
// dwWakeMask:QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE。(通常爲QS_ALLINPUT)
WINUSERAPI
DWORD
WINAPI
MsgWaitForMultipleObjects(
    __in DWORD nCount,
    __in_ecount_opt(nCount) CONST HANDLE *pHandles,
    __in BOOL fWaitAll,
    __in DWORD dwMilliseconds,
    __in DWORD dwWakeMask
);

// dwFlags:等待類型,0、MWMO_ALERTABLE、MWMO_INPUTAVAILABLE、MWMO_WAITALL(通常爲0)
WINUSERAPI
DWORD
WINAPI
MsgWaitForMultipleObjectsEx(
    __in DWORD nCount,
    __in_ecount_opt(nCount) CONST HANDLE *pHandles,
    __in DWORD dwMilliseconds,
    __in DWORD dwWakeMask,
    __in DWORD dwFlags
);

// windows內建的絕佳調試支持
WINBASEAPI
BOOL
WINAPI
WaitForDebugEvent(
    __in LPDEBUG_EVENT lpDebugEvent,
    __in DWORD dwMilliseconds
);

// 通過一個原子操作來觸發一個內核對象並等待另一個內核對象
// hObjectToSignal:必須是事件、信號量或互斥量
// hObjectToWaitOn:必須是進程、線程、作業、控制檯輸入、變更通知、事件、計時器、信號量、互斥量
// dwMilliseconds:等待時間
// bAlertable:線程處於等待狀態時,是否應該能夠對添加到隊列中的異步過程調用進行處理
WINBASEAPI
DWORD
WINAPI
SignalObjectAndWait(
    __in HANDLE hObjectToSignal,
    __in HANDLE hObjectToWaitOn,
    __in DWORD dwMilliseconds,
    __in BOOL bAlertable
);

4、C++封裝

無(ps:可通過其他文章查看使用)

5、順藤摸瓜

如果多個線程等待同一個內核對象,那麼當對象被觸發時,系統如何決定喚醒哪個線程?
算法機制:先入先出,通常情況下等待時間最長的線程得到對象;但是,系統內部的一些操作可能會改變這種行爲。(舉個栗子:調試進程使得線程頻繁
    掛起和恢復)
SignalObjectAndWait:特別受歡迎,原因一:觸發一個對象並等待另一個對象,讓一個函數完成兩個操作可以節省處理時間;原因二:觸發和等待操作是通過原子方式執行。

鳴謝

覺的我寫的幫幫噠, 發個紅包賞賞賞

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章