線程阻塞狀態(tài)
線程從創(chuàng)建铜靶、運行到結(jié)束總是處于下面五個狀態(tài)之一:新建狀態(tài)、就緒狀態(tài)停团、運行狀態(tài)旷坦、阻塞狀態(tài)及死亡狀態(tài)。
![](http://www.blogjava.net/images/blogjava_net/santicom/360%E6%88%AA%E5%9B%BE20110901211600850.jpg)
所謂阻塞狀態(tài)是正在運行的線程沒有運行結(jié)束佑稠,暫時讓出CPU秒梅,這時其他處于就緒狀態(tài)的線程就可以獲得CPU時間,進入運行狀態(tài)舌胶。
線程運行過程中捆蜀,可能由于各種原因進入阻塞狀態(tài):
- 線程調(diào)用一個在I/O上被阻塞的操作,即該操作在輸入輸出操作完成之前不會返回到它的調(diào)用者幔嫂;
- 線程試圖得到一個鎖辆它,而該鎖正被其他線程持有;
- 線程通過調(diào)用sleep方法進入睡眠狀態(tài)履恩;
- 線程在等待某個觸發(fā)條件锰茉;
- ......
以上原因可以劃分成三大類:線程阻塞、線程睡眠切心、線程掛起飒筑。
線程阻塞、線程睡眠绽昏、線程掛起的形象比喻
操作系統(tǒng)中阻塞协屡、睡眠、掛起的區(qū)別形象解釋全谤。首先這些術(shù)語都是對于線程來說的肤晓,對線程的控制就好比你控制了一個雇工為你干活。
線程阻塞:本來你讓雇工掃地认然,結(jié)果掃帚被偷了或被鄰居家借去了补憾,你又沒讓雇工繼續(xù)干別的活,他就只好睡覺了季眷。雇工一旦發(fā)現(xiàn)掃帚回來了余蟹,他就會自己去干活的。
線程睡眠:你主動對雇工說:“你睡覺去吧子刮,某時某刻過來報到威酒,然后接著干活”。
掛起線程:你對主動對雇工說:“你睡覺去吧挺峡,用著你的時候我主動去叫你葵孤,然后接著干活”杆怕。
線程阻塞
線程在運行過程中必然要獲取訪問系統(tǒng)資源惊橱,暫且不說CPU,線程運行肯定要和磁盤進行交互蔼紧,繼而發(fā)生IO操作狭姨,IO操作勢必要引起等待宰啦,在資源未讀取完成苏遥,線程必然要等待,那么在等待IO完成這個部分就是阻塞狀態(tài)赡模。所以從這里來看田炭,阻塞是一種被動的方式,由于獲取資源獲取不到而引起的等待漓柑。
本人將線程阻塞細分成兩類:
- 等待阻塞:等待IO等硬件資源
- 同步阻塞:等待信號量等內(nèi)核資源教硫,延伸的還有互斥鎖、條件變量等線程同步對象(線程Join操作原理估計也是同步阻塞)辆布。
線程睡眠
當一個線程獲取資源失斔簿亍(但沒有觸發(fā)線程阻塞)暫時無法繼續(xù)運行時,可以有兩種處理方式:
- 放棄CPU锋玲,自己睡眠景用,觸發(fā)調(diào)度;
- 占有CPU惭蹂,忙等待丛肢,使用完自己的時間。
從這里看剿干,睡眠是一種主動的方式蜂怎,且僅僅作為一種處理手段。睡眠不僅僅用于使線程進入阻塞狀態(tài)置尔,更多的杠步,我們可以在適當?shù)臅r候設置讓線程睡眠一定的時間。
線程掛起
線程掛起是操作系統(tǒng)調(diào)度線程的手段之一榜轿,操作系統(tǒng)在調(diào)度時暫停當前線程的執(zhí)行幽歼,將其切換至阻塞狀態(tài),將CPU資源調(diào)度給其他的線程谬盐;在需要的時候甸私,操作系統(tǒng)可以恢復某線程的執(zhí)行權(quán)限,將其切換至就緒狀態(tài)飞傀。
因此常見的線程掛起是一種被動的方式皇型,場景如下:
- 分時操作系統(tǒng)當前進程時間片用完時,被動切換至阻塞狀態(tài)
- 搶占式操作系統(tǒng)當前進程被高優(yōu)先級進程搶占后砸烦,被動切換至阻塞狀態(tài)
某些情況下線程掛起是主動觸發(fā)的弃鸦,比如調(diào)試程序時,線程執(zhí)行到某個斷點幢痘,會主動掛起線程(trap陷入)唬格。
進程掛起
線程掛起主要考慮CPU資源的調(diào)度,而進程掛起主要考慮是內(nèi)存資源的分配。
掛起進程在操作系統(tǒng)中可以定義為暫時被淘汰出內(nèi)存的進程购岗,機器的資源是有限的汰聋,在資源不足的情況下,操作系統(tǒng)對在內(nèi)存中的程序進行合理的安排喊积,其中有的進程被暫時調(diào)離出內(nèi)存马僻,當條件允許的時候,會被操作系統(tǒng)再次調(diào)回內(nèi)存注服,重新進入等待被執(zhí)行的狀態(tài)即就緒態(tài)。
操作系統(tǒng)為什么要引入掛起狀態(tài)措近?掛起狀態(tài)涉及到中級調(diào)度溶弟,因為當內(nèi)存中的某個程序需要大的內(nèi)存空間來執(zhí)行,但這時內(nèi)存有沒有空余空間了瞭郑,那么操作系統(tǒng)就回根據(jù)調(diào)度算法把一些進程放到外存中去辜御,以騰出空間給正在執(zhí)行的程序的數(shù)據(jù)和程序,所以引如了掛起狀態(tài)屈张。引起掛起狀態(tài)的原因有如下幾方面:
(1)終端用戶的請求擒权。當終端用戶在自己的程序運行期間發(fā)現(xiàn)有可疑問題時,希望暫停使自己的程序靜止下來阁谆。亦即碳抄,使正在執(zhí)行的進程暫停執(zhí)行;若此時用戶進程正處于就緒狀態(tài)而未執(zhí)行场绿,則該進程暫不接受調(diào)度剖效,以便用戶研究其執(zhí)行情況或?qū)Τ绦蜻M行修改。我們把這種靜止狀態(tài)成為“掛起狀態(tài)”焰盗。
(2)父進程的請求璧尸。有時父進程希望掛起自己的某個子進程,以便考察和修改子進程熬拒,或者協(xié)調(diào)各子進程間的活動爷光。
(3)負荷調(diào)節(jié)的需要。當實時系統(tǒng)中的工作負荷較重澎粟,已可能影響到對實時任務的控制時蛀序,可由系統(tǒng)把一些不重要的進程掛起,以保證系統(tǒng)能正常運行活烙。
(4)操作系統(tǒng)的需要哼拔。操作系統(tǒng)有時希望掛起某些進程,以便檢查運行中的資源使用情況或進行記賬瓣颅。
(5)對換的需要倦逐。為了緩和內(nèi)存緊張的情況,將內(nèi)存中處于阻塞狀態(tài)的進程換至外存上。