作為開發(fā)者,我們必須深入了解死鎖的概念、產生原因、檢測方法以及應對策略,以確保程序的穩(wěn)定性和可靠性
本文將詳細剖析Linux程序死鎖,并提供一系列有效的解決方案
一、死鎖的基本概念 死鎖是指在多道程序系統(tǒng)中,一組進程中的每個進程都無限期地等待被該組進程中的另一個進程所占有且永遠不會被釋放的資源,這種現(xiàn)象稱為系統(tǒng)處于死鎖狀態(tài),簡稱死鎖
處于死鎖狀態(tài)的進程成為死鎖進程
系統(tǒng)發(fā)生死鎖會大量浪費系統(tǒng)資源,甚至會導致整個系統(tǒng)崩潰
二、死鎖的產生原因 死鎖的產生原因主要有兩個:一是競爭資源,系統(tǒng)提供的資源有限,不能滿足每個進程的需求;二是多道程序運行時,進程的推進順序不合理
系統(tǒng)的資源分為兩類:永久性資源和臨時性資源
永久性資源(可重生資源)是指那些可供進程重復利用、長期存在的資源,如內存、CPU等硬件資源,以及數(shù)據(jù)文件、共享程序代碼等軟件資源
臨時性資源(消耗性資源)是指由某個進程產生、只為另一個進程使用一次,或經過短暫時間后便不可再使用的資源,如I/O和時鐘中斷、消息等
兩種資源都可能導致發(fā)生死鎖
三、死鎖的必要條件 對于永久性資源,產生死鎖有四個必要條件: 1.互斥條件:進程獨占所分配到的資源且排他使用
進程互斥使用資源,即任意時刻一個資源只能被一個進程使用,其他進程申請一個正在被占有的資源時,申請者要等待直至資源被占用者釋放
2.不可剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行剝奪,只能由使用者自愿釋放
3.請求和保持條件:進程已經得到至少一個資源,但又提出了新的資源請求,而該資源又被其他進程所占有,此時進程會等待直至得到所需資源,在等待期間繼續(xù)占用已得到的資源
4.循環(huán)等待條件:在發(fā)生死鎖時,必然存在一個進程等待隊列,其中每個進程所占有的資源同時被另一個進程所申請,即前一個進程占有后一個進程所申請的資源,形成一個進程等待環(huán)路
四、死鎖的檢測與解除 解決死鎖的方法可分為兩類:一是不讓死鎖發(fā)生;二是等死鎖發(fā)生后再解決
具體有以下四種方法: 1.預防死鎖:通過破壞產生死鎖的必要條件(除第一個互斥條件外的其他條件)來防止死鎖發(fā)生
此方法會導致系統(tǒng)資源利用率過低
2.避免死鎖:在資源的動態(tài)分配過程中,采取某種方法防止系統(tǒng)進入不安全狀態(tài),從而避免死鎖發(fā)生
此方法只需以較弱的限制條件為代價,并獲得較高的資源利用率
3.檢測死鎖:允許系統(tǒng)運行過程中發(fā)生死鎖,事先不用采取預防、避免措施
4.解除死鎖:與死鎖檢測相配套的措施,用于將進程從死鎖狀態(tài)下解脫出來
在允許進程動態(tài)申請資源的前提下,可以做出如下規(guī)定:一個進程在申請新資源的要求不能立即得到滿足時,該進程進入等待狀態(tài)
而處于等待狀態(tài)下的進程的全部資源可以被他人剝奪,被剝奪的資源重新放到資源表中
該方法適合那些狀態(tài)是容易保存和恢復的資源,例如CPU、內存等
但此方法實現(xiàn)起來較為復雜,且代價很大
因為一個資源在使用一段時間后被強制剝奪會造成前階段工作失效,甚至可能出現(xiàn)某個進程反復申請和釋放資源的情況,使得進程執(zhí)行無限期推遲,還增加了系統(tǒng)開銷,延長了進程的周轉時間,降低了系統(tǒng)的吞吐量和性能
五、死鎖的預防策略 預防死鎖的主要策略是破壞前面提到的四個必要條件之一: 1.破壞互斥條件:使資源盡可能變?yōu)楣蚕碣Y源
某些資源(如讀寫鎖)可以允許多個線程同時訪問
2.破壞請求和保持條件:要求進程在開始時一次性申請所有需要的資源
這樣可以避免在獲得部分資源后繼續(xù)等待其他資源的情況
3.破壞不可剝奪條件:允許操作系統(tǒng)強制剝奪某些資源
在某些情況下,如果一個進程需要其他資源而無法獲取,可以通過釋放當前資源,等待一段時間后重新嘗試獲取所有資源
4.破壞循環(huán)等待條件:為所有資源排序,并要求進程按照預定義的順序請求資源
這樣可以避免循環(huán)等待的發(fā)生
六、死鎖的避免策略 避免死鎖的基本思想是:系統(tǒng)對進程發(fā)出的每個系統(tǒng)能滿足的資源申請進行動態(tài)檢測,并根據(jù)檢查結果決定是否分配資源;如果分配后系統(tǒng)可能發(fā)生死鎖,則不予分配,反之予以分配
由于避免死鎖策略中允許進程動態(tài)地申請資源,所以系統(tǒng)要提供某種方法,在分配資源前,先分析資源分配的安全性
當估計到可能有死鎖發(fā)生時及時設法避免
如果操作系統(tǒng)能保證所有進程能在有限時間內獲得需要的全部資源,則稱系統(tǒng)處于“安全狀態(tài)”,否則就是不安全的
所謂的安全狀態(tài)是指,如果系統(tǒng)的所有進程構成了一個安全序列,則系統(tǒng)處于安全狀態(tài)
銀行家算法是最經典的死鎖避免算法之一
七、死鎖的檢測與解除策略 死鎖檢測的實質是確定是否存在“循環(huán)等待”條件,檢測算法確定死鎖發(fā)生并識別出與死鎖有關的進程和資源
1.死鎖檢測算法:當任一進程申請一個已被其他進程占有的資源時,通過反復查找資源分配表和進程等待表,來確定該進程對這個資源的申請是否會導致環(huán)路,若是,便確定出現(xiàn)死鎖
2.死鎖解除:要解除死鎖就要剝奪資源,那就要考慮如下幾個問題:被犧牲的進程重新運行或回退到某一點繼續(xù)運行;如何保證不發(fā)生“餓死現(xiàn)象”,即如何保證不會總是剝奪同一個進程的資源,從而導致該進程處于“饑餓狀態(tài)”;“最小代價”,即最經濟合算的算法,使得進程回退帶來的開銷最小
八、實例分析:死鎖的代碼示例
下面是一個簡單的死鎖代碼示例,在該示例中,兩個線程分別獲取不同的鎖,然后嘗試獲取對方已經占有的鎖,最終導致死鎖:
include