1. 程式人生 > 其它 >作業系統概念 第7章 死鎖

作業系統概念 第7章 死鎖

程序因申請資源而等待而等待狀態無法結束的現象稱為死鎖。本章主要討論死鎖的產生條件與解決方法。

系統模型

為了描述程序與資源的關係,需要建立模型。資源被分為若干中,種類是相同的,因此我們只需要考慮每種資源有多少個。

程序首先要申請資源,成功後資源分配給該程序,程序使用資源,完成後釋放資源。

資源分配圖中,用圓圈來表示程序,用方框表示一種型別的資源,其中的每個黑點表示一個資源例項。由程序指向資源的邊為申請邊,由資源指向程序的邊為分配邊。

死鎖的必要條件

死鎖有四個必要條件:

  • 互斥:同一資源例項不能被多個程序同時共享。
  • 非搶佔:程序不可以搶佔另一個程序正在使用的資源。
  • 佔有等待:所有參與死鎖構成的程序中,每個程序必須至少佔有一個資源,且至少等待一個被其他死鎖程序佔有的資源。
  • 迴圈等待:上述佔有等待的關係構成有向環路。

表現在資源分配圖上,有環是死鎖的必要不充分條件。

死鎖的處理方法

忽略死鎖確實是一種常用的策略,但這裡我們考慮真正的死鎖處理方法:預防死鎖、避免死鎖、檢測並恢復死鎖。

死鎖預防

預防死鎖指確保四個必要條件中至少有一個不成立,其通過限制資源的申請來實現。

破壞互斥條件通常是不可行的。

破壞佔有等待的常見策略是確保等待時不佔有。具體的方案包括等待時釋放資源,或者只有在不擁有資源時才能申請資源且必須一口氣申請完所有資源。這些方法會大幅度降低資源利用率且會導致飢餓現象。

允許搶佔,即程序在等待時,其已經擁有的資源可以被搶佔。這種方法只適用於那些狀態可以輕易儲存和恢復的資源。

破除迴圈,通常要求請求必須按照某種全序來逐個進行。

死鎖避免

死鎖避免演算法通過動態檢查資源分配狀態,確保迴圈等待條件不可能程理。它分析各程序以後如何申請資源的資訊,考慮現有可用資源、每個程序已經分配和還需要分配的資源的數目的關係。

如果按照某個順序為每個程序分配資源,等待該程序完成後再繼續,如此操作就可以避免死鎖,那麼這個順序稱為安全序列。存在安全序列的系統狀態稱為安全狀態。安全狀態一定不會發生死鎖。

死鎖避免演算法的思想是始終保持系統處於安全狀態中。

資源分配圖演算法

資源分配圖演算法用於處理每種資源型別只有一個資源例項的情況。

在前述資源分配圖的基礎上,增加一類邊稱為需求邊,由程序指向某個資源,表示在將來的某個時候該程序要申請這種資源。當申請發生時,需求邊變成申請邊。當資源釋放時,申請邊變成需求邊。

資源分配圖演算法只有在申請邊變成分配邊不會導致出現由分配邊時才允許申請。

銀行家演算法

銀行家演算法的思想是,在銀行放貸的過程中,如果當前已經不能滿足一個客戶的全部需要時,我們不給他再分配更多。具體而言,我們每次分配,都保證系統處在安全狀態,在滿足這一條件下,能分就分,不再考慮更多。

銀行家演算法需要維護一些資料結構。假設有 \(n\) 個程序,\(m\) 種資源,\(a[i]\) 表示第 \(i\) 種資源現有例項的數量,\(M[i][j]\) 表示程序 \(i\) 對第 \(j\) 種資源的最大需求,\(A[i][j]\) 表示已經分配給程序 \(i\) 多少個資源 \(j\)\(N[i][j]\) 表示程序 \(i\) 還需要多少個資源 \(j\)。這裡顯然有 \(A+N=M\)。以下我們用 \(X_i\) 表示矩陣 \(X\)\(i\) 行向量。

銀行家演算法由安全性演算法和資源請求演算法兩部分構成。

安全性演算法:

work[]=a;
finish[]=0;
While true:
	Find i s.t. finish[i]=0, Ni<=work;
	If i: work+=Ai, finish[i]=1;
	Else Return finish[]=1;

資源請求演算法:

// 假設限制 Pi 發出了請求 Ri
If Ri>Ni: Error();
If Ri>a: Wait();
// 嘗試分配
a-=Ri;
Ai+=Ri;
Ni-=Ri;
If IsSafe()==false: a+=Ri, Ai-=Ri, Ni+=Ri, Wait();

死鎖檢測

資源都只有單個例項的情況下,直接用等待圖即可。

資源具有多個例項的情況下,類似銀行家演算法,維護資料結構 a,A,R(各程序當前的資源請求情況),利用死鎖檢測演算法來判斷系統是否處於死鎖狀態。

死鎖檢測演算法

work[]=a;
finish[]=0;
While true:
	Find i s.t. finish[i]=0, Ri<=work;
	If i: work+=Ai, finish[i]=1;
	Else Return finish[]=1;

注意死鎖檢測演算法和安全性演算法的唯一區別是找 i 時判斷條件中,安全性演算法是 Ni<=work 而死鎖檢測演算法是 Ri<=work。從這裡我們可以看出安全性演算法的要求比死鎖檢測演算法要高。安全性演算法考慮了未來,而死鎖檢測演算法只關心當下。

由於死鎖檢測演算法的複雜度較高,一般執行頻率較低,或只在系統狀態滿足特定條件時執行。

死鎖恢復

死鎖恢復的自動解決方案有兩類。

終止程序,可以終止所有死鎖程序,也可以從代價最小的程序開始,貪心地一個個終止直到死鎖解除。

資源搶佔,需要選擇一個犧牲品,將它的狀態回滾到一個安全的位置。為了防止飢餓,可以在犧牲品選擇的代價中引入與回滾次數相關的因子。