調(diào)度算法:Sleep并不總是如你預(yù)想的那樣起作用
作為上一篇文章”即使運(yùn)行高優(yōu)先級(jí)線程,低優(yōu)先線程也能運(yùn)行”的另一個(gè)反面例子,人們會(huì)認(rèn)為調(diào)用 Sleep(0) 是一種放棄 CPU 時(shí)間片的簡(jiǎn)單方法。舉個(gè)例子,如果消費(fèi)者線程目前沒(méi)有數(shù)據(jù)可以處理,則可以調(diào)用此函數(shù)來(lái)出讓 CPU 時(shí)間片,以等待生產(chǎn)者線程產(chǎn)生需要的數(shù)據(jù)。
讓我們回想一下,調(diào)度程序會(huì)查找優(yōu)先級(jí)最高的可運(yùn)行線程,如果存在平局,則所有候選項(xiàng)大致平均共享 CPU。線程可以調(diào)用 Sleep(0) 來(lái)放棄其時(shí)間片,從而減少其在 CPU 中的份額。但請(qǐng)注意,這并不能保證其他線程將運(yùn)行。
如果存在具有最高優(yōu)先級(jí)的唯一可運(yùn)行線程,它可以調(diào)用 Sleep(0),并保持很長(zhǎng)一段時(shí)間,但它不會(huì)放棄 CPU。這是因?yàn)?Sleep 的時(shí)間為零會(huì)釋放分配給它的時(shí)間片,但使線程可運(yùn)行。由于它是唯一具有最高優(yōu)先級(jí)的可運(yùn)行線程,因此它會(huì)立即恢復(fù) CPU。如果沒(méi)有其他人排隊(duì),你實(shí)際上并沒(méi)有將時(shí)間片出讓給其他線程。
因此,如果使用 Sleep(0) 作為不那么有效的出讓 CPU 的方法,它永遠(yuǎn)不會(huì)允許運(yùn)行優(yōu)先級(jí)較低的線程。這意味著各種后臺(tái)活動(dòng)(如索引)永遠(yuǎn)不會(huì)有機(jī)會(huì)運(yùn)行,因?yàn)槟愕某绦蛘加昧怂?CPU 時(shí)間。更重要的是,你的程序從未真正釋放 CPU 的事實(shí),意味著計(jì)算機(jī)永遠(yuǎn)不會(huì)進(jìn)入低功耗狀態(tài)。筆記本電腦會(huì)更快地耗盡電池電量并運(yùn)行得更熱,終端服務(wù)器將無(wú)休止地消耗 CPU 時(shí)間片。
最好的辦法是等待正確的同步對(duì)象,以便線程進(jìn)入睡眠狀態(tài),直到有工作要做。如果你由于某種原因不能這樣做,至少 Sleep 一個(gè)非零的時(shí)間值。這樣,在短暫的時(shí)刻,你的線程不可運(yùn)行,而其他線程(包括優(yōu)先級(jí)較低的線程) 有機(jī)會(huì)運(yùn)行。(這也將在一定程度上降低功耗,盡管不如等待正確的同步對(duì)象那么多。)
總結(jié)
我們需要了解 CPU 時(shí)間片在各個(gè)線程上的調(diào)度原理,Sleep(0) 和 Sleep(1) 雖然只是參數(shù)上的不同,但底層運(yùn)行邏輯卻有很大的區(qū)別。
由于程序可能會(huì)運(yùn)行在各種不同配置的系統(tǒng)上,簡(jiǎn)單的使用 Sleep 來(lái)進(jìn)行線程同步,將產(chǎn)生預(yù)料不到的偏差,你絕對(duì)不希望這樣。
所以,正如原文作者指出的,多線程下的線程協(xié)調(diào)工作,還是使用內(nèi)核同步對(duì)象比較好。
最后
Raymond Chen的《The Old New Thing》是我非常喜歡的博客之一,里面有很多關(guān)于Windows的小知識(shí),對(duì)于廣大Windows平臺(tái)開(kāi)發(fā)者來(lái)說(shuō),確實(shí)十分有幫助。
本文來(lái)自:《Consequences of the scheduling algorithm: Sleeping doesn’t always help》


























