互斥鎖死鎖狀態詳解

在編程中,引入了對象互斥鎖的概念,來保證共享數據操作的完整性。每個對象都對應於一個可稱爲” 互斥鎖” 的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。那麼到底怎樣的情形纔會產生死鎖呢?
典型的兩種死鎖情形:
(一)線程自己將自己鎖住
一般情況下,如果同一個線程先後兩次調用lock,在第二次調⽤用時,由於鎖已經被佔用,該線程會掛起等待佔用鎖的線程釋放鎖,然而鎖正是被自己佔用着的,該線程又被掛起而沒有機會釋放鎖,因此 就永遠處於掛起等待狀態了,於是就形成了死鎖(Deadlock)。
(二)多線程搶佔鎖資源被困
又如線程A獲 得了鎖1,線程B獲得了鎖2,這時線程A調用lock試圖獲得鎖2,結果是需要掛起等待線程B釋放 鎖2,而這時線程B也調用lock試圖獲得鎖1,結果是需要掛起等待線程A釋放鎖1,於是線程A和B都 永遠處於掛起狀態了,死鎖再次形成。

二、計算機系統中的死鎖

1、資源分類
(一)可重用性資源和消耗性資源
可重用資源:可供用戶重複使用多次的資源。
性質:
1》每一個可重用性資源中的單元只能分配給一個進程(或線程)使用,不允許多個進程(或線程)共享。
2》可重用性資源的使用順序:
請求資源—->使用資源—->釋放資源
3》系統中每一類可重用性資源中的單元數目是相對固定的,進程(或線程)在運行期間既不能創建也不能刪除它。

可消耗性資源:又稱臨時性資源,是由進程(或線程)在運行期間動態的創建和消耗的。
性質:
1》每一類可消耗性資源的單元數目在進程(或線程)運行期間是可以不斷變化的,有時可能爲0.
2》進程,或線程)在運行過程中可以不斷的創建可消耗性資源的單元,將它們放入該資源類的緩衝區中,以增加該資源類的單元數目。
3》進程(或線程)在運行過程中可請求若干個可消耗性資源,用於進程(或線程)自己的消耗不再將它們返回給該資源類中。
可消耗性資源通常是由生產者進程(或線程)創建,由消費者進程(或線程)消耗。

(二)可搶佔性資源和不可搶佔性資源
可搶佔性資源:☞某進程(或線程)在獲得該類資源後,該資源可以被其他進程(或線程)或系統搶佔。
CPU和主存均屬於可搶佔性資源。
不可搶佔性資源:☞系統一旦把某資源分配該進程(或線程)之後,就不能強行收回,只能在進程(或線程)用完之後自行釋放。
磁帶機、打印機等都屬於不可搶佔性資源。

2、引起死鎖的原因
(一)競爭不可搶佔資源引起死鎖
如:共享文件時引起死鎖
這裏寫圖片描述

系統中擁有兩個進程P1和P2,它們都準備寫兩個文件F1和F2。而這兩者都屬於可重用和不可搶佔性資源。如果進程P1在打開F1的同時,P2進程打開F2文件,當P1想打開F2時由於F2已結被佔用而阻塞,當P2想打開1時由於F1已結被佔用而阻塞,此時就會無線等待下去,形成死鎖。

(二)競爭可消耗資源引起死鎖
如:進程通信時引起死鎖

這裏寫圖片描述

系統中擁有三個進程P1、P2和P3,m1、m2、m3是3可消耗資源。進程P1一方面產生消息m1,將其發送給P2,另一方面要從P3接收消息m3。而進程P2一方面產生消息m2,將其發送給P3,另一方面要從P1接收消息m1。類似的,進程P3一方面產生消息m3,將其發送給P1,另一方面要從P2接收消息m2。
如果三個進程都先發送自己產生的消息後接收別人發來的消息,則可以順利的運行下去不會產生死鎖,但要是三個進程都先接收別人的消息而不產生消息則會永遠等待下去,產生死鎖。

(三)進程推進順序不當引起死鎖

這裏寫圖片描述
上圖中,如果按曲線1的順序推進,兩個進程可順利完成;如果按曲線2的順序推進,兩個進程可順利完成;如果按曲線3的順序推進,兩個進程可順利完成;如果按曲線4的順序推進,兩個進程將進入不安全區D中,此時P1保持了資源R1,P2保持了資源R2,系統處於不安全狀態,如果繼續向前推進,則可能產生死鎖。

三、死鎖的定義、必要條件和處理方法

1、死鎖的定義:如果一組進程(或線程)中的每一個進程(或線程)都在等待僅由該組進程中的其他進程(或線程)才能引發的事件,那麼該組進程(或線程)是死鎖的(Deadlock)。
2、產生死鎖的必要條件
(1)互斥條件。進程(線程)所申請的資源在一段時間內只能被一個進程(線程)鎖佔用。
(2)請求和保持條件。進程(線程)已經佔有至少一個資源,但又提出了新的資源請求,而該資源卻被其他進程(線程)佔用。
(3)不可搶佔條件(不可剝奪條件)。進程(線程)已獲得的資源在未使用完之前不能被搶佔。
(4)循環等待條件(環路等待條件)。在發生死鎖時,必然存在一個進程(線程)—-資源的循環鏈。
3、處理死鎖的方法
(1)預防死鎖。破壞死鎖產生的必要條件中的一個或多個。注意,互斥條件不能被破壞,否則會造成結果的不可再現性。
(2)避免死鎖。在資源分匹配過程中,防止系統進入不安全區域。
(3)檢測死鎖。通過檢測機構檢測死鎖的發生,然後採取適當措施解除死鎖。
(4)解除死鎖。在檢測機構檢測死鎖發生後,採取適當措施解除死鎖。

四、利用銀行家算法避免死鎖

1、銀行家算法中的數據結構
(1)可利用資源向量Available[m]。m爲系統中的資源種類數,如果向量Available[j] = K,則表示系統中Rj類資源由K個。
(2)最大需求矩陣Max[n][m]。m爲系統中的資源種類數,n爲系統中正在運行的進程(線程)數,如果Max[i][j] = K,則表示進程i需要Rj類資源的最大數目爲K個。
(3)分配矩陣Allocation[n][m]。m爲系統中的資源種類數,n爲系統中正在運行的進程(線程)數,如果Allocation[i][j] = K,則表示進程i當前已分得Rj類資源的數目爲K個。
(4)需求矩陣Need[n][m]。m爲系統中的資源種類數,n爲系統中正在運行的進程(線程)數,如果Need[i][j] = K,則表示進程i還需要Rj類資源K個。
以上三個矩陣間的關係:
Need[i][j] = Max[i][j] - Allocation[i][j]

2、銀行家算法
設Request( i)是進程Pi的請求向量,如果Request(i) [j] = K,表示進程Pi需要K個Rj類型的資源。
(1)如果Request(i) [j] <= Need[i][j],轉向步驟(2)。
(2)如果Request(i) [j] <= Available[j] ,轉向步驟(3)。
(3)系統嘗試着把資源分給進程Pi。
Available[j] = Available[j] - Request(i) [j];
Allocation[i][j] = Allocation[i][j] + Request(i) [j];
Need[i][j] = Need[i][j] - Request(i) [j];
(4)系統執行安全性算法,檢查此次資源分配後系統是否處於安全狀態。

3、安全性算法
(1)設置兩個向量:
1》工作向量Work[m],它表示系統可提供給進程繼續運行所需要的各類資源數目,初始值Work = Available。
2》Finish:它表示系統是否有足夠的資源分配給進程,使其運行完成。開始時Finish[i] = false,當有足夠的資源分配給進程時Finish[i] = true。
(2)從進程(線程)集合中找到一個能滿足下述條件的進程(線程)。
1》Finish[i] = false
2》Need[i][j] <= Work[j],如果找到轉到步驟3》,沒找到轉到步驟4》。
3》Work[j] = Work[j] + Allocation[i][j] ;
Finish[i] = true;
go to step 2;
4》如果所有進程(線程)的Finish[i] = true都滿足,表示系統處於安全狀態,反之系統處於不安全狀態。

發佈了115 篇原創文章 · 獲贊 48 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章