死鎖加拓展問題(全網最細)

寫在前面:我在複習過程中整理的面試系列文章,全部免費分享給大家,適合保研和考研還有平常複習,需要的請移步我的個人原創gong主號:程序員寶藏(號如其名,誠不欺你),回覆關鍵字:複試上岸,即可獲取!

如果覺得對你有幫助,點個贊鼓勵一下我,嘿嘿!

在這裏插入圖片描述

正文開始

1.死鎖的定義

在多道程序系統中,由於多個進程的併發執行,改善了系統資源的利用率並提高了系統的處理能力。然而,多個進程的併發執行也帶來了新的問題——死鎖。

所謂死鎖,是指多個進程因競爭資源而造成的一種僵局(互相等待),若無外力作用,這些進程都將無法向前推進。

【這裏可能會問】:外力作用,什麼是外力?答:資源剝奪;撤銷進程;進程回退(參看後面的死鎖解除)

【死鎖實例】:某計算機系統中只有一臺打印機和一臺輸入設備,進程P1正佔用輸入設備,同時又提出使用打印機的請求,但此時打印機正被進程P2所佔用,而P2在未釋放打印機之前,又提出請求使用正被P1佔用的輸入設備。這樣,兩個進程相互無休止地等待下去,均無法繼續執行,此時兩個進程陷入死鎖狀態。

2.死鎖產生的原因

一、系統資源的競爭

通常系統中擁有的不可剝奪資源,其數量不足以滿足多個進程運行的需要,使得進程在運行
過程中,會因爭奪資源而陷入僵局,如磁帶機、打印機等。只有對不可剝奪資源的競爭纔可能產生死鎖,對可剝奪資源的競爭是不會引起死鎖的。


二、進程推進順序非法

進程在運行過程中,請求和釋放資源的順序不當,也同樣會導致死鎖。例如,併發進程P1, P2分別保持了資源R1,R2, 而進程P1 申請資源R2、進程P2申請資源R1 時,兩者都會因爲所需資源被佔用而阻塞。

信號量使用不當也會造成死鎖。進程間彼此相互等待對方發來的消息,也會使得這些進程間
無法繼續向前推進。例如,進程A等待進程B發的消息,進程B又在等待進程A發的消息,可以看出進程A和B不是因爲競爭同一資源,而是在等待對方的資源導致死鎖。

3.死鎖產生的必要條件

產生死鎖必須同時滿足以下4個條件,只要其中任意一個條件不成立,死鎖就不會發生。

  1. 互斥條件:進程要求對所分配的資源(如打印機)進行排他性控制,即在一段時間內某資源僅爲一個進程所佔有。此時若有其他進程請求該資源,則請求進程只能等待。

  2. 不剝奪條件:進程所獲得的資源在未使用完之前,不能被其他進程強行奪走,即只能由獲得該資源的進程自己來釋放(只能是主動釋放)。

  3. 請求並保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源已被其他進程佔有,此時請求進程被阻塞,但對自己已獲得的資源保持不放。

  4. 循環等待條件:存在一種進程資源的循環等待鏈,鏈中每個進程已獲得的資源同時被鏈中下一個進程所請求。即存在一個處於等待態的進程集合{P1, P2, …, Pn},其中Pi 等待的資源被Pi+1 (i=0,1, … ,n-l) 佔有,Pn等待的資源被P0佔有,如圖所示:

【注意】:直觀上看,循環等待條件似乎和死鎖的定義一樣,其實不然。按死鎖定義構成等待環所要求的條件更嚴,它要求Pi等待的資源必須由Pi+1來滿足,而循環等待條件則無此限制。例如,系統中有兩臺輸出設備, P0佔有一臺,Pk佔有另一臺,且k不屬於集合{0,1,… ,n} 。Pn等待一臺輸出設備,它可
從P0獲得,也可能從Pk獲得。因此,雖然Pn,P0和其他一些進程形成了循環等待圈,但Pk不在圈內,若Pk釋放了輸出設備,則可打破循環等待,如圖所示。因此循環等待只是死鎖的必要條件。

資源分配圖含圈而系統又不一定有死鎖的原因是,同類資源數大於1 。但若系統中每類資源
都只有一個資源,則資源分配圖含圈就變成了系統出現死鎖的充分必要條件。

要注意區分不剝奪條件與請求並保持條件。下面用一個簡單的例子進行說明:若你手上拿着
一個蘋果(即便你不打算吃),別人不能把你手上的蘋果拿走,則這就是不剝奪條件;若你左手拿着一個蘋果,允許你右手再去拿一個蘋果,則這就是請求並保持條件。

4.死鎖的處理策略

爲使系統不發生死鎖,必須設法破壞產生死鎖的4個必要條件之一,或允許死鎖產生,但當
死鎖發生時能檢測出死鎖,並有能力實現恢復。有以下三種處理策略:

  1. 死鎖預防
    設置某些限制條件,破壞產生死鎖的4 個必要條件中的一個或幾個,以防止發生死鎖。

  2. 避免死鎖
    在資源的動態分配過程中,用某種方法防止系統進入不安全狀態,從而避免死鎖。

  3. 死鎖的檢測及解除
    無須採取任何限制性措施,允許進程在運行過程中發生死鎖。通過系統的檢測機構及時地檢測出死鎖的發生,然後採取某種措施解除死鎖。

【比較】預防死鎖和避免死鎖都屬於事先預防策略,預防死鎖的限制條件比較嚴格,實現起來較爲簡單,但往往導致系統的效率低,資源利用率低;避免死鎖的限制條件相對寬鬆,資源分配後需要通過算法來判斷是否進入不安全狀態,實現起來較爲複雜。死鎖的幾種處理策略的比較見表:

死鎖預防

防止死鎖的發生只需破壞死鎖產生的4 個必要條件之一即可。

  1. 破壞互斥條件
    若允許系統資源都能共享使用,則系統不會進入死鎖狀態。但有些資源根本不能同時訪問,
    如打印機等臨界資源只能互斥使用。

所以,破壞互斥條件而預防死鎖的方法不太可行,而且在有的場合應該保護這種互斥性。

  1. 破壞不剝奪條件
    當一個已保持了某些不可剝奪資源的進程請求新的資源而得不到滿足時,它必須釋放已經保
    持的所有資源,待以後需要時再重新申請。這意味着,一個進程已佔有的資源會被暫時釋放,或者說是被剝奪,或從而破壞了不剝奪條件。
    該策略實現起來比較複雜,釋放已獲得的資源可能造成前一階段工作的失效,反覆地申請請和釋放資源會增加系統開銷,降低系統吞吐量。

這種方法常用於狀態易於保存和恢復的資源,如CPU的寄存器及內存資源,一般不能用於打印機之類的資源。

  1. 破壞請求並保持條件
    採用預先靜態分配方法,即進程在運行前一次申請完它所需要的全部資源,在它的資源未滿
    足前,不把它投入運行。一旦投入運行,這些資源就一直歸它所有,不再提出其他資源請求,這樣就可以保證系統不會發生死鎖。

這種方式實現簡單,但缺點也顯而易見,系統資源被嚴重浪費,其中有些資源可能僅在運行
初期或運行快結束時才使用,甚至根本不使用。而且還會導致"飢餓“現象,由於個別資源長期被其他進程佔用時,將致使等待該資源的進程遲遲不能開始運行。

  1. 破壞循環等待條件
    爲了破壞循環等待條件,可採用順序資源分配法。首先給系統中的資源編號,規定每個進程
    必須按編號遞增的順序請求資源,同類資源一次申請完。也就是說,只要進程提出申請分配資源Ri, 則該進程在以後的資源中請中就只能申請編號大於Ri的資源。

這種方法存在的問題是,編號必須相對穩定,這就限制了新類型設備的增加;儘管在爲資源
編號時已考慮到大多數作業實際使用這些資源的順序,但也經常會發生作業使用資源的順序與系統規定順序不同的情況,造成資源的浪費;此外,這種按規定次序申請資源的方法也必然會給用戶的編程帶來麻煩。

死鎖避免

避免死鎖同樣屬於事先預防策略,但並不是事先採取某種限制措施破壞死鎖的必要條件,而是在資源動態分配過程中,防止系統進入不安全狀態,以避免發生死鎖。這種方法所施加的限制條件較弱,可以獲得較好的系統性能。

避免死鎖的方法中,允許進程動態地申請資源,但系統在進行資源分配之前,應先計算此次分配的安全性。若此次分配不會導致系統進入不安全狀態,則允許分配;否則讓進程等待。

【安全狀態】是指系統能按某種進程推進順序(P1, P2, …, Pn) 爲每個進程Pi分配其所需的資源,直至滿足每個進程對資源的最大需求,使每個進程都可順序完成。此時稱P1, P2,···, Pn爲安全序列。若系統無法找到一個安全序列,則稱系統處於不安全狀態。

【注意】:並非所有的不安全狀態都是死鎖狀態,但當系統進入不安全狀態後,便可能進入死鎖狀態;反之,只要系統處於安全狀態,系統便可避免進入死鎖狀態。


銀行家算法

銀行家算法是最著名的死鎖避免算法,其【思想】是:把操作系統視爲銀行家,操作系統管理的資源相當於銀行家管理的資金,進程向操作系統請求分配資源相當於用戶向銀行家貸款。操作系統按照銀行家制定的規則爲進程分配資源。進程運行之前先聲明對各種資源的最大需求量,當進程在執行中繼續申請資源時,先測試該進程已佔用的資源數與本次申請的資源數之和是否超過該進程聲明的最大需求量。若超過則拒絕分配資源,若未超過則再測試系統現存的資源能否滿足該進程尚需的最大資源量,若能滿足則按當前的申請量分配資源,否則也要推遲分配。

相關數據結構和實例感興趣請自行百度(公式括號矩陣表格不太好打出來,嘿嘿嘿!)

死鎖的檢測和解除

前面介紹的死鎖預防和避免算法,都是在爲進程分配資源時施加限制條件或進行檢測,若系
統爲進程分配資源時不採取任何措施,則應該提供死鎖檢測和解除的手段。

  • 資源分配圖
    系統死鎖可利用資源分配圖來描述。如下圖所示,用圓圈代表一個進程,用框代表一類資源。由於一種類型的資源可能有多個,因此用框中的一個圓代表一類資源中的一個資源。從進程到資源的有向邊稱爲請求邊,表示該進程申請一個單位的該類資源;從資源到進程的邊稱爲分配邊,表示該類資源已有一個資源分配給了該進程。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-utQr0mAS-1588853368544)(https://imgkr.cn-bj.ufileos.com/88165550-3fdd-4130-ad8f-835c879fceee.png)]

【注意】判斷某種資源是否有剩餘空間,應用它的資源數量減去它在資源分配圖中的出度。

在該圖示的資源分配圖中,進程P1已經分得了兩個R1資源,並又請求一個R2資源;進程P2分得了一個R1資源和一個R2資源,並又請求一個R1資源。

  • 死鎖定理
    簡化資源分配圖可檢測系統狀態S是否爲死鎖狀態。簡化方法如下:
  1. 在資源分配圖中,找出既不阻塞又不孤點的進程Pi【即找出一條有向邊與它相連,且該有向邊對應資源的申請數量小於等於系統中已有的空閒資源數量,如在上圖中,R1沒有空閒資源,R2有一個空閒資源。若所有連接該進程的邊均滿足上述條件,則這個進程能繼續運行直至完成,然後釋放它所佔有的所有資源】。消去它所有的請求邊和分配邊,使之成爲孤立的結點。在下圖(a)中,P1是滿足這一條件的進程結點,將P1 的所有邊消去,便得到下圖(b)所示的情況。繼續簡化便得到(c)的情況。

S爲死鎖的條件是當且僅當S狀態的資源分配圖是不可完全簡化的,該條件爲死鎖定理。


死鎖解除

一旦檢測出死鎖,就應立即採取相應的措施來解除死鎖。死鎖解除的主要方法有:

  1. 資源剝奪法。掛起某些死鎖進程,並搶佔它的資源,將這些資源分配給其他的死鎖進程。但應防止被掛起的進程長時間得不到資源而處於資源匱乏的狀態。
  2. 撤銷進程法。強制撤銷部分甚至全部死鎖進程並剝奪這些進程的資源。撤銷的原則可以按進程優先級和撤銷進程代價的高低進行。
  3. 進程回退法。讓一(或多)個進程回退到足以迴避死鎖的地步,進程回退時自願釋放資源而非被剝奪。要求系統保持進程的歷史信息,設置還原點。

【拓展】:死鎖與飢餓的區別?
一組進程處於死鎖狀態是指組內的每個進程都在等待一個事件,而該事件只可能由組內的另一個進程產生。這裏所關心的主要是事件是資源的獲取和釋放。
與死鎖相關的另一個問題是無限期阻塞(Indefinite Blocking) 或飢餓(Starvation) , 即進程在信號最內無窮等待的情況。
產生飢餓的【主要原因】是:在一個動態系統中,對於每類系統資源,操作系統需要確定一個分配策略,當多個進程同時申請某類資源時,由分配策略確定資源分配給進程的次序。有時資源分配策略可能是不公平的,即不能保證等待時間上界的存在。在這種情況下,即使系統沒有發生死鎖,某些進程也可能會長時間等待。當等待時間給進程推進和響應帶來明顯影響時,稱發生了進程”飢餓",當“飢餓”到一定程度的進程所賦予的任務即使完成也不再具有實際意義時,稱該進程被“餓死”。
“飢餓”並不表示系統一定會死鎖,但至少有一個進程的執行被無限期推遲。"飢餓”與死鎖的主要差別如下:

  1. 進入“飢餓”狀態的進程可以只有一個,而因循環等待條件而進入死鎖狀態的進程卻必
    須大於等於兩個。
  2. 處於“飢餓''狀態的進程可以是一個就緒進程,如靜態優先權調度算法時的低優先權進程,而處於死鎖狀態的進程則必定是阻塞進程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章