深入分析Sleep(0)與Sleep(1)的區別
目的:
有時候我們想讓執行緒不被排程一定的時間,也就是說讓執行緒睡眠一段時間。
API 介面:
在 Win32中可以呼叫 Sleep,SleepEx 和 SwitchToThread 三個API。
VOID WINAPI Sleep(DWORD dwMilliseconds);
DWORD WINAPI SleepEx(DWORD dwMilliseconds, BOOl bAlertable);
BOOl WINAPI SwitchToThread();
在託管程式碼中,我們可以呼叫靜態方法 Thread.Sleep。
分析:
Sleep 介面均帶有表示睡眠時間長度的引數 timeout。呼叫以上提到的 Sleep 介面,會有條件地將呼叫執行緒從當前處理器上移除,並且有可能將它從執行緒排程器的可執行佇列中移除。這個條件取決於呼叫 Sleep 時timeout 引數。
當 timeout = 0, 即 Sleep(0),如果執行緒排程器的可執行佇列中有大於或等於當前執行緒優先順序的就緒執行緒存在,作業系統會將當前執行緒從處理器上移除,排程其他優先順序高的就緒執行緒執行;如果可執行佇列中的沒有就緒執行緒或所有就緒執行緒的優先順序均低於當前執行緒優先順序,那麼當前執行緒會繼續執行,就像沒有呼叫 Sleep(0)一樣。
當 timeout > 0 時,如:Sleep(1),會引發執行緒上下文切換:呼叫執行緒會從執行緒排程器的可執行佇列中被移除一段時間,這個時間段約等於 timeout 所指定的時間長度。為什麼說約等於呢?是因為睡眠時間單位為毫秒,這與系統的時間精度有關。通常情況下,系統的時間精度為 10 ms,那麼指定任意少於 10 ms但大於 0 ms 的睡眠時間,均會向上求值為 10 ms。
而呼叫 SwitchToThread() 方法,如果當前有其他就緒執行緒線上程排程器的可執行佇列中,始終會讓出一個時間切片給這些就緒執行緒,而不管就緒執行緒的優先順序的高低與否。
結論:
由上面的分析可以看出,如果我們想讓當前執行緒真正睡眠一下子,最好是呼叫 Sleep(1) 或 SwitchToThread()。