一、什么是死鎖
死鎖(Deadlock):是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。稱此時系統處於死鎖狀態或系統產生了死鎖。
稱這些永遠在互相等待的進程為死鎖進程。
所占用的資源或者需要它們進行某種合作的其它進程就會相繼陷入死鎖,最終可能導致整個系統處於癱瘓狀態。
學到這里,我們可能會對前面提到的幾個名詞感到困惑,死鎖,飢餓,死循環一樣嗎?都代表什么意思呢?
死鎖和飢餓是操作系統導致的問題,而死循環則是被管理者的問題,也就是程序員的問題。
針對上面銀行家算法,防止死鎖發生可采取的措施:
(1)最多允許4個哲學家同時坐在桌子周圍。
(2)僅當一個哲學家左右兩邊的筷子都可用時,才允許他拿筷子。
(3)給所有哲學家編號,奇數號的哲學家必須首先拿左邊的筷子,偶數號的哲學家則反之。
這里給出一個不會發生死鎖的哲學家進餐過程的算法描述。
semaphore S[5] = {1,1,1,1,1};//5雙筷子 semaphore mutex = 4;//最多允許4個哲學家 Pi() { while(1) { P(mutex); P(S[i]); 拿起左邊的叉子; P(S[i+1]mod5); 拿起右邊的叉子; 吃通心粉; 放下左邊的叉子; V(S[i]); 放下右邊的叉子; V(S[i+1]mod5); V(mutex); } }
二、產生死鎖的必要條件
互斥條件
不可剝奪條件
占有並請求條件
循環等待條件
三、產生死鎖的原因
主要原因有兩個:競爭臨界資源和進程推進順序不當。
總之就是對不可剝奪資源的不合理分配,可能導致死鎖。
一個小問題:
一個OS有20個進程,競爭使用65個同類資源,申請方式是逐個進行的,一旦某個進程獲得它所需要的全部資源,則立即歸還所有資源。每個進程最多使用三個資源。若僅考慮這類資源,該系統有無可能產生死鎖,為什么?
答:不可能。因為死鎖產生的原因有兩點:系統資源不足或推進順序不當,在本題中,進程所需的最大資源數為60,而系統共有該類資源65個,其資源數已足夠系統內各進程使用。
四、死鎖的處理策略
五、死鎖概念總結
六、死鎖的預防
死鎖的預防是通過破壞產生死鎖的必要條件之一,是系統不會產生死鎖。簡單方法是在系統運行之前就采取措施,即在系統設計時確定資源分配算法,消除發生死鎖的任何可能性。該方法雖然比較保守、資源利用率低,但因簡單明了並且安全可靠,仍被廣泛采用。這是一種預先的靜態策略。
破壞互斥條件
破壞不可剝奪條件
破壞請求和保持條件
破壞循環等待條件
產生死鎖的四個必要條件中,互斥條件和不可剝奪條件由共享資源本身的使用特性所決定的,因此不好破壞,相反還應加以保證,實用的死鎖預防辦法就是通過破壞產生死鎖的占用並請求條件和循環等待條件。
總結
七、死鎖的避免
安全序列
王道考研的老師在將安全序列的時候,舉了一個銀行給BAT三家公司借錢的例子用來引出銀行家算法,很有意思。
這時候如果將30億借給了B公司,那么手里還有10億元,這10億已經小於3家公司最小的最多還會借的錢數,沒有公司能夠達到提出的最大要求,這樣銀行的錢就會打水漂了!!!
如果是這種情況呢?
這樣按照T->B->A的順序借錢是沒有問題的,是安全的。
按照A->T->B的順序借錢也是沒有問題的。
這樣我們就會得到安全序列、不安全序列和死鎖的關系了。
注意:
(1)系統在某一時刻的安全狀態可能不唯一,但這不影響對系統安全性的判斷。
(2)安全狀態是非死鎖狀態,而不安全狀態並不一定是死鎖狀態。即系統處於安全狀態一定可以避免死鎖,而系統處於不安全狀態則僅僅可能進入死鎖狀態。
原因是如果進入了不安全狀態,但是沒有進程去請求資源,並且有進程提前歸還了一些資源,這樣就不會死鎖。
銀行家算法
銀行家問題的本質:
要設法保證系統動態分配資源后不進入不安全狀態,以避免可能產生的死鎖。
即:每當進程提出資源請求且系統的資源能夠滿足該請求時,系統將判斷如果滿足此次資源請求,系統狀態是否安全,如果判斷結果為安全,則給該進程分配資源,否則不分配資源,申請資源的進程將阻塞。
當Pi發出資源請求后,系統按下述步驟進行檢查:
1.如果Requesti > Needi,則出錯。
2.如果Requesti>Available,則Pi 阻塞;
3.系統試探把要求的資源分配給進程Pi,並修改下面數據結構中的數值:
Availablei=Availablei-Requesti;
Allocationi=Allocationi+Requesti;
Needi = Needi- Requesti;
4. 系統執行安全性算法,檢查此次資源分配后,系統是否處於安全狀態。若安全,正式將資源分配給進程Pi,以完成本次分配;否則,將試探分配作廢,恢復原來的資源分配狀態,讓進程Pi等待。
銀行家算法從避免死鎖的角度上說是非常有效的,但是,從某種意義上說,它缺乏實用價值,因為很少有進程能夠在運行前就知道其所需資源的最大值,而且進程數也不是固定的,往往在不斷地變化(如新用戶登錄或退出),況且原本可用的資源也可能突然間變成不可用(如磁帶機可能壞掉)。因此,在實際中,如果有,也只有極少的系統使用銀行家算法來避免死鎖。
八、死鎖的檢測和解除
死鎖的檢測和恢復技術是指定期啟動一個軟件檢測系統的狀態,若發現有死鎖存在,則采取措施恢復之。
死鎖的檢測
檢查死鎖的辦法就是由軟件檢查系統中由進程和資源構成的有向圖是否構成一個或多個環路,若是,則存在死鎖,否則不存在。
由於死鎖是系統中的惡性小概率事件,死鎖檢測程序的多次執行往往都不會調用一次死鎖解除程序,而這卻增加了系統開銷,因此在設計操作系統時需要權衡檢測精度與時間開銷。
死鎖的解除
常見的死鎖解除方法有以下兩種:
(1)撤消進程法
撤消全部死鎖進程:代價太大,該做法很少用。
最小代價撤消法:首先計算死鎖進程的撤消代價,然后依次選擇撤消代價最小的進程,逐個地撤消死鎖進程,回收資源給其他進程,直至死鎖不復存在。進程的撤消代價往往與進程的優先級、占用處理機的時間等成正比。
(2)掛起進程法 (剝奪資源)
使用掛起/激活機構掛起一些進程,剝奪它們的資源以解除死鎖,待條件滿足時,再激活進程。目前掛起法比較受到重視。
顯然,無論哪一種解除死鎖的方法,都需要很大的開銷。但是死鎖的檢測與解除辦法不對系統的資源分配等加任何限制,因此是對付死鎖的諸辦法中導致資源利用率最高的一種辦法,在對安全性要求高的大型系統中常用。
根據銀行家算法,引出了這樣一個公式的證明。