天天看點

線程同步 等待函數 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:特别受歡迎,原因一:觸發一個對象并等待另一個對象,讓一個函數完成兩個操作可以節省處理時間;原因二:觸發和等待操作是通過原子方式執行。
           

鳴謝

線程同步 等待函數 WaitForSingleObject WaitForMultipleObjects

繼續閱讀