1 產生死鎖的原因和必要條件
死鎖(Deadlock):指多個進程在運行過程中,因爭奪資源而造成的一種僵局。當進程處於這種狀態時,若無外力作用,它們都將無法再向前推進。
例:使用信號量造成死鎖的典型
P1 P2
wait(D) wait(E)
wait(E) wait(D)
signal(D) signal(E)
signal(E) signal(D)
死鎖發生:雙方都擁有部分資源,同時在請求對方已佔有的資源。
請求推進的次序與對非剝奪性資源的爭用都是造成死鎖的原因。
產生死鎖的原因可歸結爲如下兩點:
1)競爭資源。系統中供多個進程共享的資源如打印機、公用隊列等的數目不滿足需要時,會引起資源競爭而產生死鎖。
2)進程間推進順序非法。進程在運行過程中,請求和釋放資源的順序不當,同樣會導致死鎖。
1.1 競爭資源引起進程死鎖
可把系統中的資源分爲兩類:
�可剝奪性資源:分配給進程後可以被高優先級的進程剝奪。如CPU和主存。
�不可剝奪性資源:分配給進程後只能在進程用完後釋放。如磁帶機、打印機等。
永久性資源和臨時性資源
�永久性:打印機。可順序重複使用
臨時性:進程產生被其他進程短暫使用的資源,如數據資源:“生產者/消費者”算法中的信號量。它可能引起死鎖。
1.2 進程推進順序不當引起死鎖
進程在運行中具有異步性特徵,多個進程按向前推進的順序有兩種情況:
1)推進順序合法
2)推進順序非法
1.3 產生死鎖的必要條件
形成死鎖的四個必要條件(四個條件都具備就會死鎖,缺一就不會死鎖)
①互斥條件:進程對所分配到的資源進行排他性使用;
②請求和保持條件:進程已經保持了至少一個資源,又提出新的資源請求,而新請求資源被其他進程佔有只能造成自身進程阻塞,但對自己已獲得的其他資源保持不放,必然影響其他進程;
③不剝奪條件:進程已獲得的資源未使用完之前不能被剝奪,只能在使用完時由自己釋放;
④環路等待條件
1.4 處理死鎖的基本方法
事先預防:
①預防死鎖
設置限制條件,破壞四個必要條件的一個或幾個,預防發生死鎖。
較易實現。限制條件的嚴格也會導致系統資源利用率和系統吞吐量降低。
②避免死鎖
不須事先限制,破壞四個必要條件,而是在資源的動態分配過程中,用某種方法去防止系統進入不安全狀態,從而避免發生死鎖。
這種事先加以較弱限制的方法,實現上有一定難度,但可獲較高的資源利用率及系統吞吐量,目前在較完善的系統中,常用此方法來避免發生死鎖。
事後處理:
③檢測死鎖。
允許系統運行過程中發生死鎖,但通過系統檢測機構可及時的檢測出,能精確確定與死鎖有關的進程和資源;然後採取適當的措施,從系統中將已發生的死鎖清除掉。
④解除死鎖。
與死鎖檢測配套的一種措施。
常用的實施方法:撤銷或掛起一些進程,以便回收一些資源並將他們分配給已阻塞進程,使之轉爲就緒以繼續運行。
死鎖的檢測與解除措施,有可能使系統獲得較好的資源利用率和吞吐量(死鎖機率不一定很高),但在實現上難度也最大。
2 預防死鎖的方法
2.1 預防死鎖
資源的排他性無法更改,故在其他3個條件上入手
①摒棄“請求和保持”條件:所有進程開始運行前,必須一次性的申請其在整個運行過程所需的全部資源(AND)。算法簡單、易於實現且很安全。但缺點是資源浪費嚴重、或進程延遲運行。
②摒棄“不剝奪”條件:允許進程先運行,但當提出的新要求不被滿足時必須釋放它已保持的所有資源,待以後需要時再重新申請。實現比較複雜且付出很大代價。可能會造成前功盡棄,反覆申請和釋放等情況。
③摒棄“環路等待”條件
有序設置資源:將所有資源按類型進行線性排隊,賦予不同序號。所有進程對資源的請求必須嚴格按照資源序號遞增的次序提出,這樣在所形成的資源分配圖中,不可能會出現環路。
與前兩種策略比較,資源利用率和系統吞吐量都有較明顯的改善。但也存在嚴重問題:資源編號限制新設備的增加;應用中的使用設備順序與規定的順序並不協調;限制了用戶編程自由。
2.2 避免死鎖
上述方法限制條件都太強;造成一定的應用不便。採用避免死鎖的方法則是隻施加較弱限制條件,從而獲得令人滿意的系統性能。
安全狀態:系統能按某種進程順序爲每個進程分配所需資源,直至滿足每個進程對資源的最大需求,並能順利完成。
不安全狀態:系統無法找到一種使多個進程能夠順利分配資源執行完的安全序列。
每次資源分配時,都應分析判斷資源分配圖,看該次操作後是否有安全序列。若沒有,說明該操作會使系統進入不安全狀態。
只要使系統始終處於安全狀態,便可避免發生死鎖。
不是所有的不安全狀態都是死鎖狀態。
2.3 銀行家算法避免死鎖
最有代表性的避免死鎖的算法,是Dijkstra的銀行家算法。由於該算法能用於銀行系統現金貸款的發放而得名。
【思路描述】:隨時對系統中的所有資源信息進行統計,包括每種資源的數量、已分配給各進程的數量;每當進程提出某種資源請求時判斷該請求分配後是否安全,如果安全才分配。對每個資源請求的處理都要保證系統始終從一個安全狀態到另一個安全狀態。
(1)T0時刻的初始狀態是安全的;
(2)下面出現P1請求資源的操作,具體請求向量爲Request1(1,0,2),利用銀行家算法進行檢查該操作是否是安全可行的:
1)兩個基本判斷
Request1(1,0,2)<=Need1(1,2,2)
Request1(1,0,2)<=Available1(3,3,2)
2)先假設爲P1分配資源,並修改Available,Allocation1和Need1向量。
3) Request1(1,0,2)後新的資源狀態表下再判斷新資源狀態是否是安全的。
找到一個安全序列{P1,P3,P4,P0,P2},因此係統是安全的,該請求是安全的,可將假設真正實施,將P1所申請的資源分配給它。
3 死鎖的檢測與解除
當系統爲進程分配資源時,若未採取任何限制性措施,則系統必須提供檢測和解除死鎖的手段,爲此係統必須:
1.保存有關資源的請求和分配信息;
2.提供一種算法,以利用這些信息來檢測系統是否已進入死鎖狀態。
3.1 資源分配圖
•系統死鎖可利用資源分配圖來描述。
•圓圈表示進程
•方框表示一類資源,其中的一個點代表一個該類資源
•請求邊由進程指向方框中的資源
•分配邊則由方框中的一個點即資源。
3.2 死鎖定理
利用資源分配圖簡化法來檢測死鎖。
簡化方法如下:
1.在資源分配圖中找出一個既不阻塞又非獨立的進程結點Pi,在順利的情況下運行完畢,釋放其佔有的全部資源。
2.由於釋放了資源,這樣能使其它被阻塞的進程獲得資源繼續運行。消去了Pi的邊。
3.經過一系列簡化後,若能消去圖中所有邊,使結點都孤立,稱該圖是可完全簡化的。
S狀態爲死鎖狀態的充分條件是當且僅當S狀態的資源分配圖是不可完全簡化的。
3.3 死鎖的解除
當發現進程死鎖時,便應立即把它們從死鎖狀態中解脫出來。常採用的方法是:
1.剝奪資源。從其他進程剝奪足夠數量的資源給死鎖進程以解除死鎖狀態。
2.撤銷進程。最簡單的是讓全部進程都死掉;溫和一點的是按照某種順序逐個撤銷進程,直至有足夠的資源可用,使死鎖狀態消除爲止。