1. 程式人生 > >死鎖小結

死鎖小結

資源的分類         計算機系統中的資源分為兩類:可搶佔的和不可搶佔的。         可搶佔資源可以從擁有它的程序中搶佔而不會產生任何副作用,例如儲存器就是一類可搶佔的資源;不可搶佔資源是指在不引起相關的計算失敗的情況下,無法把它從佔有它的程序處搶佔過來,例如一個程序已開始刻盤,突然將CD燒錄機分配給另一個程序,那麼將劃壞CD盤,在任何時刻CD燒錄機都是不可搶佔的。         總的來說,死鎖和不可搶佔資源有關。 死鎖概述
        一. 死鎖定義         如果一個程序集合中的每個程序都在等待只能由該程序集合中的其他程序才能引發的事件,那麼該程序集合就是死鎖的。         二. 資源死鎖         在大多數情況下,每個程序所等待的事件是釋放該程序集合中的其他程序已經佔有的資源。換言之,這個死鎖程序集合中的每一個程序都在等待另一個死鎖的程序已經佔有的資源。但是由於所有程序都不能執行,它們中的任何一個都無法釋放資源,所以沒有一個程序可以被喚醒。這種死鎖稱為資源死鎖。         三. 資源死鎖的四個必要條件
  • 互斥條件:每個資源要麼已經分配給了一個程序,要麼就是可用的
  • 佔有並等待條件:已經得到了某個資源的程序可以再請求新的資源
  • 不可搶佔條件:已經分配給一個程序的資源不能強制性地被搶佔,它只能被佔有它的程序顯式地釋放。
  • 環路等待條件:死鎖發生時,系統中一定有由兩個或兩個以上的程序組成的一條環路,該環路中的每個程序都在等待著下一個程序所佔有的資源
        死鎖發生時,以上四個條件是同時滿足的。如果任何一個條件不成立,死鎖就不會發生。 死鎖建模         死鎖建模可利用有向圖實現。在有向圖中有兩個節點:用圓形標識的程序,用方形表示的資源。從資源節點到程序節點的有向邊代表該資源已被請求、授權並被程序佔用。         假設有三個程序(A、B、C)及三個資源(R、S、T)。下圖展示了三個程序對資源的請求和釋放及呈現的結果:             
死鎖處理         有四種處理死鎖的策略:
  • 採用鴕鳥演算法:最簡單的解決方法是鴕鳥演算法,把頭埋到沙子裡,假裝根本沒有問題發生。
  • 檢測死鎖並恢復:讓死鎖發生,檢測它們是否發生,一旦發生死鎖,採取行動解決問題。
  • 仔細對資源進行分配:通過仔細地對資源進行分配,動態地避免死鎖
  • 從源頭處預防死鎖產生:通過破壞引起死鎖的四個必要條件之一,從源頭處防止死鎖產生
        下面來具體討論這四種策略。 鴕鳥演算法         每個人對該方法的看法都不同。但大多數人都會以處理死鎖的代價/回報比做出理性選擇。 死鎖檢測&恢復         一. 死鎖檢測         1. 每種型別一個資源的死鎖檢測         構建資源分配圖,採用深度優先遍歷演算法確定是否存在環路。這種演算法是依次將每一個節點作為一棵樹的根節點,並進行深度優先搜尋,如果再次碰到已經遇到過的節點,那麼就算找到了一個環。如果從任何給定的節點出發的弧都被窮舉了,那麼就回溯到前面的節點。如果回溯到根並且不能再深入下去,那麼從當前節點出發的子圖中就不包含任何環。如果所有的節點都是如此,那麼整個圖就不存在環也就是說系統不存在死鎖。         2. 每種型別多個資源的死鎖檢測         構建向量矩陣,利用向量矩陣演算法模擬資源分配。這種演算法的第一步是尋找可以執行完畢的程序,該程序的特點是它有資源請求並且該請求可被當前的可用資源滿足。這一選中的程序隨後就被執行完畢,在這段時間內它釋放自己持有的所有資源並將它們返回到可用資源庫中。然後這一程序被標記為完成。如果所有的程序最終都能執行完畢的話,就不存在死鎖的情況。         二. 死鎖恢復         1. 利用搶佔恢復         在某些情況下,可能會臨時將某個資源從它的當前所有者那裡轉移到另一個程序。這種做法是否可行主要取決於該資源本身的特性(可搶佔、不可搶佔)。用這種方法恢復通常比較困難或者說不可能。若選擇掛起某個程序,則在很大程度上取決於哪一個程序擁有比較容易回收的資源。         2. 利用回滾恢復         這種方法可以在死鎖發生時將程序復位到一個更早的狀態,那時它還沒有取得所需的資源,接著就把這個資源分配個一個死鎖程序。如果復位後的程序試圖重新獲得對該資源的控制,它就必須一直等到該資源可用時為止。         3. 通過殺死程序恢復         有可能的話,最好殺死可以從頭開始重新執行而且不會帶來副作用的程序。 死鎖避免
        是否存在一種演算法總能做出正確的選擇從而避免死鎖呢?答案是肯定的,但條件是事先要獲得一些特定的資訊。但從本質上來說,死鎖避免是不可能的,因為它需要獲知未來的請求,而這些請求時不可知的。         一. 利用資源軌跡圖         如下圖所示,我們看到一個處理兩個程序和兩種資源的模型。橫軸表示程序A執行的命令,縱軸表示程序B執行的命令。程序A在I1處請求一臺印表機,在I3處釋放,在I2處請求一臺繪圖儀,在I4處釋放。程序B在I5到I7之間需要繪圖儀,在I6到I8之間需要印表機。         兩個程序交替執行,一旦系統進入由I1、I2和I5、I6組成的矩形區域,那麼最後一定會到達I2和I6的交叉點,因為程序的執行不可能後退,程序的運動方向只可能是向上或向右,這時就會產生死鎖。         
        二. 利用銀行家演算法         考慮這樣一個系統,有5個程序P0 ~ P4,3種資源型別A、B、C。資源型別A有10個例項,資源型別B有5個例項,資源型別C有7個例項,假定在時刻T0,系統狀態如下:         
  • Allocation:定義每個程序現在所分配的各種資源型別的例項數量
  • Max:定義每個程序的最大需求
  • Available:定義每種資源型別僅存的例項數量
  • Need:定義每個程序還需要的剩餘的資源
        這樣,在假定程序P1再請求1個資源型別A和2個資源型別C,這樣Request=(1,0,2),為了確定這個請求是否可以立即允許,首先檢測Request<= Available,即(1,0,2) <= (3,3,2),其值為真,接著這個假定請求被滿足,就會產生如下新狀態:                  如此,每次請求都在安全範圍內,直到完成所有請求,便是銀行家演算法的大概思路。 死鎖預防         通過破壞引起死鎖的四個必要條件之一,從源頭處防止死鎖產生。         一. 破壞互斥條件:         就是在系統裡取消互斥。若資源不被一個程序獨佔使用,那麼死鎖是肯定不會發生的。但一般來說在所列的四個條件中,“互斥”條件是無法破壞的。因此,在死鎖預防裡主要是破壞其他幾個必要條件,而不去涉及破壞“互斥”條件。         二. 破壞佔有並等待條件: 破壞“佔有並等待”條件,就是在系統中不允許程序在已獲得某種資源的情況下,申請其他資源。即要想出一個辦法,阻止程序在持有資源的同時申請其他資源。有兩種方法:         (1)建立程序時,要求它申請所需的全部資源,系統或滿足其所有要求,或什麼也不給它。這是所謂的 “ 一次性分配”方案。
  • 存在問題:很多程序知道執行時才知道它需要多少資源;這種方法的資源利用率不是最優的。
        (2)要求當一個程序請求資源時,先暫時放棄其當前佔用的所有資源,然後再嘗試一次獲得所需的全部資源。           三. 破壞不可搶佔條件: 破壞“不可搶佔”條件就是允許對資源實行搶奪。有兩種方法:         (1)如果佔有某些資源的一個程序進行進一步資源請求被拒絕,則該程序必須釋放它最初佔有的資源,如果有必要,可再次請求這些資源和另外的資源。         (2)如果一個程序請求當前被另一個程序佔有的一個資源,則作業系統可以搶佔另一個程序,要求它釋放資源。只有在任意兩個程序的優先順序都不相同的條件下,這個才能預防死鎖。         四. 破壞環路等待條件:         破壞“迴圈等待”條件的一種方法,是將系統中的所有資源統一編號,程序可在任何時刻提出資源申請,但所有申請必須按照資源的編號順序(升序)提出。這樣做就能保證系統不出現環路,也就避免了死鎖。例如:         有兩個程序A和B,兩個資源i和j,假定A已經獲得了i,B已經獲得了j,只有在A請求j而B請求i的情況下才會產生死鎖。假定i和j是不同的資源,它們會具有不同的編號。若i>j,那麼A不允許請求j,因為這個編號小於A已有資源的編號;若i<j,那麼B不允許請求i,因為這個編號小於B已有資源的編號。不論哪種情況下都不可能產生死鎖。並且對於多於兩個程序的情況,同樣的邏輯依然成立。