1. 程式人生 > >死鎖概念以及預防解決方法簡介 多線程上篇(八)

死鎖概念以及預防解決方法簡介 多線程上篇(八)

最簡 send 人員 記錄 事情 定期 資源分配圖 避免死鎖 最終

在前面不止一次的提到過死鎖。 所謂死鎖(Deadlock) 是指多個進程在運行過程中因爭奪資源而造成的一種僵局(DeadlyEmbrace),當進程處於這種僵持狀態時,若無外力作用,它們都將無法再向前推進。 死鎖的定義:集合中的每一個進程都在等待只能由本集合中的其他進程才能引發的事件,那麽該組進程是死鎖的。 也就是說集合中的人需要等待本集合中的其他人來幫忙, 但是,可怕的是所有的人都是這狀態。 引起死鎖的主要原因是:需要采用互斥方法訪問的、不可以被搶占的資源“。 因為需要互斥,所以就產生了競爭,出現了競爭就會出現等待,但是資源又不可被搶占,所以可能會被別人一直占有,那麽就可能無限的等待,這就形成了死鎖。

資源角度

技術分享圖片 計算機資源可以從兩個維度進行劃分,重用性以及搶占性。 不管是可重用資源還是消耗性資源,他們都不是可以任意請求的 系統中可重用資源的個數相對來說比較固定,消耗性資源盡管是個數不固定,動態的,但是某瞬間也都是有個數的,所以也不是可以任意請求的。 所以不管是否可重用,只要有競爭訪問,就可能出現死鎖。 對於不可搶占資源,一旦被請求了,如果不能夠釋放,那麽別人就必須要等待。 可搶占資源即使被分配,仍舊可以被搶占,所以這類資源不會引起死鎖。 所以,從資源的角度看,只需要關註是否是可搶占資源,如果不可搶占,那麽就有可能出現死鎖。

資源分配圖

為了直觀的分析死鎖的情況,可以使用資源分配圖
是一種描述資源申請與分配關系的圖 使用圓圈表示進程,矩形表示資源; 箭頭表示資源的申請與釋放,資源->進程表示分配,進程->資源表示資源申請。 如下圖所示,表示P1獲得了R1在等待R2,P2獲得了R2 在等待R1 技術分享圖片

死鎖產生情況

競爭不可搶占資源

P1 P2 wait(R1) wait(R2) wait(R2) wait(R1) 如上所示,進程P1和P2,一個先申請資源R1,一個先申請資源R2,一旦資源R1和R2同時被兩個不同的進程獲得,將會進入死鎖狀態。 如果一個結束之後,另一個開始,那麽就不會出現死鎖。
技術分享圖片

競爭可消耗資源

設有進程P1、P2、P3,有可消耗資源R1、R2、R3 如果如下順序推進 P1: send(p2, R1); receive(p3, R3); P2: send(p3, R2); receive(p1, R1); P3: send(p1, R3); receive(p2, R2); 如下圖所示,每個進程都先生產資源給別人,然後才會等待別人的資源,每個人最終都能夠獲得資源 技術分享圖片 如果是 P1: receive(p3, R3); send(p2, R1); P2: receive(p1, R1); send(p3, R2); P3: receive(p2, R2); send(p1, R3); 所有的人都在等待別人的資源,才會生產消息,形成了死鎖。 技術分享圖片

進程推進順序不當

下圖中,橫坐標為進程1,縱坐標為進程2 進程1的活動過程有Request(R1) Request(R2) Release(R1) Release(R2) 進程2的活動過程有Request(R2) Request(R1) Release(R2) Release(R1) 顯然,圖中的陰影區域D,陰影區域的左下角表示進程1申請了資源R1,進程2申請了資源R2,如果此時進程1申請R2或者進程2申請R1或者兩者都有,必然會發生死鎖 如果避開這個區域,比如一個進程結束後另一個開始,1號曲線或者2號曲線,或者進程1釋放了R1後,進程2才開始申請R2就不會進入死鎖 通過這種活動順序圖,可以推測出來可能會出現死鎖的時空區域。 技術分享圖片 《計算機操作系統 第四版》 圖3-14

死鎖必要條件

前面從資源以及場景的角度分析了死鎖,其根本也還是“需要采用互斥方法訪問的、不可以被搶占的資源”。
技術分享圖片 死鎖形成有四大必要條件,也就是說如果死鎖了必然存在這些。 如果不互斥,大家都可以訪問,就沒可能死鎖; 如果沒有請求和保持,比如一次性分配,如果分配不到等待別人使用後釋放即可,保持和請求必然會導致“拿走了比人需要的,還等待別人”的場景; 如果可以搶占,即使已經死鎖,肯定會被打破; 如果沒有循環等待,終究會有一個進程會自己完成,完成後便會釋放自己持有的資源,整個系統就會被激活。 所以說,想要處理死鎖,或者說避免死鎖,關鍵點就是這幾個條件,只要條件被打破,就不會存在繼續死鎖下去的可能。

死鎖解決方法

技術分享圖片 從預防-避免-檢測-解除,對死鎖的防範程度依次減弱,但是對應的資源的利用率依次提高,也就是並發程度依次變高。 預防就像接種疫苗,可能你這輩子都不會接觸到病毒。 避免就是在可能出事情的地方,做一些保障處理,比如發現有些場合人員混亂,全是二手煙,那就不進房間了。 檢測就好像是定期的體檢,沒問題繼續生活,有什麽小問題就去治療一下。 解除就是真的去看病了。

預防死鎖

預防就是事先前的準備,如同疫苗,死鎖的預防通常就是增加限制,破壞必要條件。 破壞“請求和保持” 所有的資源必須一次性分配,或者不分配,這樣能夠保障一個進程要麽就等待,要麽就可以獲得全部的資源,而不會出現保持了資源,然後再去請求的可能。 但是很顯然,資源利用率低,並發程度低 比如說有一個任務三個階段,每個階段一種資源,每個階段十分鐘,如果一次性分配的話,每個資源都會有二十分鐘的閑置,極大地浪費。 這種方案可以進一步優化,分階段處理,而不是一次性,還是剛才的示例,每個階段僅僅申請該階段的資源,使用完畢後,將資源釋放,然後再去獲取下一階段的資源 也就是說需要合理的劃分階段,一個完整任務中的一個子任務(也就是一個階段)一次性分配資源,使用完畢後釋放,再去請求,就不存在保持請求了。 破壞“不可搶占” 如果資源是可搶占的,自然就不會死鎖,終究會自動解鎖,如果能夠合理的將不可搶占資源轉換為“可搶占”那麽就可以預防死鎖 當一個進程持有了某些資源後,如果又提出了新的請求,如果該請求並不能滿足,那麽他必須釋放已有的資源,也就可以說是被搶占了 不過這個思路實現復雜,可能會付出很大的代價,比如打印機開始處理了,你現在要切換,肯定不會很容易。 破壞“循環等待” 將資源按照一定的順序進行申請,可以保證資源的有序性,也就可以破壞循環等待,正是因為資源的順序很隨意,所以才導致很容易死鎖 比如所有的進程全部都是R1然後R2,就永運不會死鎖 所以可以采取對系統內資源編號的形式,所有的資源申請必須是從小到大的順序。 如此,就肯定不會循環成環。 但是,號碼如何編?到底誰大誰小?要統計下平時資源的申請順序進行編號 然後如果新增加設備? 另外如果有些進程就是跟系統的排序不同怎麽辦?

避免死鎖

在死鎖避免方法中,把系統的狀態分為安全狀態和不安全狀態。 安全狀態就是可以找到資源分配的有序序列, 各進程可以順利推進完成。 不安全狀態如果找不到一個合理的資源分配的有序序列,不能保障各進程可以順利完成,那麽就是不安全。 當系統處於安全狀態時,可避免發生死鎖。反之,當系統處於不安全狀態時,則可能進入到死鎖狀態。 簡言之,避免死鎖就是在資源分配時,借助於算法對資源分配進行計算評估,相當於風險評估機構。 經典的算法有Dijkstra提出的銀行家算法

死鎖檢測

死鎖的檢測也是借助於算法進行處理,想要檢測死鎖 首先,系統中必須能夠記錄資源的請求和分配記錄,其次需要提供一種算法,通過對請求和分配記錄進行分析,計算出當前的狀態。

死鎖解除

如果檢測出死鎖,那麽必須進行解除,常用的解除方式有兩種,搶占資源和終止進程,本質都是強行將資源奪回到系統中。 終止進程的話最簡單的就是全部終止,將涉及的死鎖進程全部都終止掉,顯然全部終止就好像將一臺工作中的電腦強行重啟一樣,代價很大 所以還可以逐個終止,直到死鎖解除。

總結

本文對操作系統中死鎖的概念進行了簡單的介紹,不僅僅進程有死鎖,線程的運行仍舊也會有死鎖。 多線程編程中也會出現死鎖,在這些場景中,死鎖的概念是相同的---都是同一個集合中的線程都在等待本集合中的線程 對於操作系統對死鎖的處理與解決,對於編程中不無借鑒之處,我們應該深刻理解死鎖形成的條件,才能夠在編程中盡可能的避免死鎖。 原文地址:死鎖概念以及預防解決方法簡介 多線程上篇(八)

死鎖概念以及預防解決方法簡介 多線程上篇(八)