死鎖是指兩個或兩個以上的程序(執行緒)在執行過程中因爭奪資源而造成的一種僵局,若無外力作用,這些程序(執行緒)都將無法向前推進。
飢餓(starvation)指乙個程序一直得不到資源。
死鎖和飢餓都是由於程序競爭資源而引起的。飢餓一般不占有資源,死鎖程序一定占有資源。
互斥:至少有乙個資源必須處於非共享模式,即一次只有乙個程序可以使用;
占有並等待:乙個程序必須占有至少乙個資源,並等待另乙個資源,而該資源為其他程序所占有;
非搶占:資源不能被強佔,即資源只能在程序完成任務後自動釋放;
迴圈等待:有一組等待程序,p0等待的資源為p1所占有,p1等待的資源為p2所占有,……,pn-1等待的資源為pn所占有,pn等待的資源為p0所占有。
以上這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。
破壞「互斥」條件:
就是在系統裡取消互斥。若資源不被乙個程序獨佔使用,那麼死鎖是肯定不會發生的。但一般來說在所列的四個條件中,「互斥」條件是無法破壞的。因此,在死鎖預防裡主要是破壞其他幾個必要條件,而不去涉及破壞「互斥」條件。
注意:互斥條件不能被破壞,否則會造成結果的不可再現性。
破壞「占有並等待」條件:
破壞「占有並等待」條件,就是在系統中不允許程序在已獲得某種資源的情況下,申請其他資源。即要想出乙個辦法,阻止程序在持有資源的同時申請其他資源。
方法一:建立程序時,要求它申請所需的全部資源,系統或滿足其所有要求,或什麼也不給它。這是所謂的 「 一次性分配」方案。
方法二:要求每個程序提出新的資源申請前,釋放它所占有的資源。這樣,乙個程序在需要資源s時,須先把它先前占有的資源r釋放掉,然後才能提出對s的申請,即使它可能很快又要用到資源r。
破壞「不可搶占」條件:
破壞「不可搶占」條件就是允許對資源實行搶奪。
方法一:如果占有某些資源的乙個程序進行進一步資源請求被拒絕,則該程序必須釋放它最初占有的資源,如果有必要,可再次請求這些資源和另外的資源。
方法二:如果乙個程序請求當前被另乙個程序占有的乙個資源,則作業系統可以搶占另乙個程序,要求它釋放資源。只有在任意兩個程序的優先順序都不相同的條件下,方法二才能預防死鎖。
破壞「迴圈等待」條件:
破壞「迴圈等待」條件的一種方法,是將系統中的所有資源統一編號,程序可在任何時刻提出資源申請,但所有申請必須按照資源的編號順序(公升序)提出。這樣做就能保證系統不出現死鎖。
預防死鎖和避免死鎖的區別:
預防死鎖是設法至少破壞產生死鎖的四個必要條件之一,嚴格的防止死鎖的出現,而避免死鎖則不那麼嚴格的限制產生死鎖的必要條件的存在,因為即使死鎖的必要條件存在,也不一定發生死鎖。避免死鎖是在系統執行過程中注意避免死鎖的最終發生。
4.2.1.1 有序資源分配法
這種演算法按某種規則將系統中的所有資源統一編號(例如印表機為1、磁帶機為2、磁碟為3、等等),申請時必須以上公升的次序。系統要求申請程序:
對它所必須使用的而且屬於同一類的所有資源,必須一次申請完;
在申請不同類資源時,必須按各類裝置的編號依次申請。例如:程序pa,使用資源的順序是r1,r2; 程序pb,使用資源的順序是r2,r1;若採用動態分配有可能形成環路條件,造成死鎖。
採用有序資源分配法:r1的編號為1,r2的編號為2;
pa:申請次序應是:r1,r2
pb:申請次序應是:r1,r2
這樣就破壞了環路條件,避免了死鎖的發生。
4.2.1.2 銀行家演算法4.2.2.1 加鎖順序
當多個執行緒需要相同的一些鎖,但是按照不同的順序加鎖,死鎖就很容易發生。
如果能確保所有的執行緒都是按照相同的順序獲得鎖,那麼死鎖就不會發生。
按照順序加鎖是一種有效的死鎖預防機制。但是,這種方式需要你事先知道所有可能會用到的鎖,但總有些時候是無法預知的。
4.2.2.2 加鎖時限
另外乙個可以避免死鎖的方法是在嘗試獲取鎖的時候加乙個超時時間,這也就意味著在嘗試獲取鎖的過程中若超過了這個時限該執行緒則放棄對該鎖請求。若乙個執行緒沒有在給定的時限內成功獲得所有需要的鎖,則會進行回退並釋放所有已經獲得的鎖,然後等待一段隨機的時間再重試。這段隨機的等待時間讓其它執行緒有機會嘗試獲取相同的這些鎖,並且讓該應用在沒有獲得鎖的時候可以繼續執行(加鎖超時後可以先繼續執行幹點其它事情,再回頭來重複之前加鎖的邏輯)。
需要注意的是,由於存在鎖的超時,所以我們不能認為這種場景就一定是出現了死鎖。也可能是因為獲得了鎖的執行緒(導致其它執行緒超時)需要很長的時間去完成它的任務。
4.2.2.3 死鎖檢測
死鎖檢測是乙個更好的死鎖預防機制,它主要是針對那些不可能實現按序加鎖並且鎖超時也不可行的場景。
當乙個執行緒請求鎖失敗時,這個執行緒可以遍歷鎖的關係圖看看是否有死鎖發生。例如,執行緒a請求鎖7,但是鎖7這個時候被執行緒b持有,這時執行緒a就可以檢查一下執行緒b是否已經請求了執行緒a當前所持有的鎖。如果執行緒b確實有這樣的請求,那麼就是發生了死鎖(執行緒a擁有鎖1,請求鎖7;執行緒b擁有鎖7,請求鎖1)。
當然,死鎖一般要比兩個執行緒互相持有對方的鎖這種情況要複雜的多。執行緒a等待執行緒b,執行緒b等待執行緒c,執行緒c等待執行緒d,執行緒d又在等待執行緒a。執行緒a為了檢測死鎖,它需要遞進地檢測所有被b請求的鎖。從執行緒b所請求的鎖開始,執行緒a找到了執行緒c,然後又找到了執行緒d,發現執行緒d請求的鎖被執行緒a自己持有著。這時它就知道發生了死鎖。
一般來說,由於作業系統有併發,共享以及隨機性等特點,通過預防和避免的手段達到排除死鎖的目的是很困難的。這需要較大的系統開銷,而且不能充分利用資源。為此,一種簡便的方法是系統為程序分配資源時,不採取任何限制性措施,但是提供了檢測和解脫死鎖的手段:能發現死鎖並從死鎖狀態中恢復出來。因此,在實際的作業系統中往往採用死鎖的檢測與恢復方法來排除死鎖。
死鎖檢測與恢復是指系統設有專門的機構,當死鎖發生時,該機構能夠檢測到死鎖發生的位置和原因,並能通過外力破壞死鎖發生的必要條件,從而使得併發程序從死鎖狀態中恢復出來。
什麼時候進行死鎖的檢測取決於死鎖發生的頻率。如果死鎖發生的頻率高,那麼死鎖檢測的頻率也要相應提高,這樣一方面可以提高系統資源的利用率,一方面可以避免更多的程序捲入死鎖。如果程序申請資源不能滿足就立刻進行檢測,那麼每當死鎖形成時即能被發現,這和死鎖避免的演算法相近,只是系統的開銷較大。為了減小死鎖檢測帶來的系統開銷,一般採取每隔一段時間進行一次死鎖檢測,或者在cpu的利用率降低到某一數值時,進行死鎖的檢測。
一旦檢測出死鎖,就應立即釆取相應的措施,以解除死鎖。
死鎖解除的主要方法有:
資源剝奪法。掛起某些死鎖程序,並搶占它的資源,將這些資源分配給其他的死鎖程序。但應防止被掛起的程序長時間得不到資源,而處於資源匱乏的狀態。
撤銷程序法。強制撤銷部分、甚至全部死鎖程序並剝奪這些程序的資源。撤銷的原則可以按程序優先順序和撤銷程序代價的高低進行。
程序回退法。讓一(多)個程序回退到足以迴避死鎖的地步,程序回退時自願釋放資源而不是被剝奪。要求系統保持程序的歷史資訊,設定還原點。
死鎖的四個必要條件及處理死鎖
如果乙個程序集合裡面的每個程序都在等待只能由這個集合中的其他乙個程序 包括他自身 才能引發的事件,這種情況就是死鎖。這個定義可能有點拗口,下面用乙個簡單例子說明。資源a b 程序c d 描述如下 資源a和資源b,都是不可剝奪資源,現在程序c已經申請了資源a,程序d也申請了資源b,程序c接下來的操作需...
死鎖的四個必要條件以及處理策略
什麼是死鎖?如果乙個程序集合裡面的每個程序都在等待只能由這個集合中的其他乙個程序 包括他自身 才能引發的事件,這種情況就是死鎖。這個定義可能有點拗口,乙個最簡單的例子就是有資源a和資源b,都是不可剝奪資源,現在程序c已經申請了資源a,程序d也申請了資源b,程序c接下來的操作需要用到資源b,而程序d恰...
死鎖的四個必要條件
作業系統中有若干程序併發執行,它們不斷申請 使用 釋放系統資源,雖然系統的進 程協調 通訊機構會對它們進行控制,但也可能出現若干程序都相互等待對方釋放資源才能 繼續執行,否則就阻塞的情況。此時,若不借助外界因素,誰也不能釋放資源,誰也不能解 除阻塞狀態。根據這樣的情況,作業系統中的死鎖被定義為系統中...