多程式並發執行時,若出現「進程 A 持有資源 1 等資源 2,進程 B 持有資源 2 等資源 1」的循環等待,系統即陷入死鎖——所有相關進程永久阻塞。理解死鎖四大必要條件,並針對性破壞任一條件,即可從根源預防死鎖發生。
死鎖四大必要條件(缺一不可)
- 互斥條件:資源同一時間只能被一個進程佔用(如印表機、獨佔檔案)。
- 佔有並等待條件:進程已持有資源,又請求新資源被阻塞時,不釋放已持有資源。
- 非搶佔條件:進程獲得的資源未使用完前,不能被強制剝奪,只能主動釋放。
- 循環等待條件:存在進程鏈 P1→P2→...→Pn→P1,每個進程等待下一個進程持有的資源。
四大破壞策略與優缺點分析
1. 破壞互斥條件 → 允許資源共享
- 做法:採用 SPOOLing 技術(如印表機緩衝區)、讀寫分離鎖等。
- 缺點:大多數硬體資源(印表機、光碟機)物理特性決定必須互斥,適用場景極窄。
2. 破壞佔有並等待條件 → 靜態資源分配
- 做法:進程啟動前一次性申請所有所需資源,全滿足才分配,否則全不分配。
- 優點:邏輯簡單、易實現、完全避免死鎖。
- 缺點:資源利用率極低(短時間用的資源被長期佔用)、可能導致「飢餓」(永遠無法一次滿足所有資源)。
3. 破壞非搶佔條件 → 搶佔式資源控制
- 做法:進程請求新資源失敗時,強制釋放已持有資源,稍後重新申請。
- 適用:易於保存/恢復狀態的資源(CPU 時間片、記憶體頁框)。
- 缺點:實現複雜、代價高昂(需保存現場)、不適用於印表機、燒錄機等不可搶佔資源。
4. 破壞循環等待條件 → 資源有序分配法(最實用)
- 做法:將所有資源分級編號,進程必須按編號遞增順序請求資源,釋放時按遞減順序。
- 優點:資源利用率與系統吞吐量較好,工程上較易落地(如資料庫鎖升級規則)。
- 缺點:編號設計困難、新增資源類型需重新編號、若進程實際使用順序與編號不符則資源浪費。
工程實踐建議
- 資料庫:採用「鎖升級順序固定」(行鎖→頁鎖→表鎖),避免循環等待。
- 多執行緒開發:固定鎖獲取順序(如永遠先鎖 A 再鎖 B)、使用
tryLock(timeout) 避免無限等待、縮小臨界區範圍。
- 作業系統層面:Windows/Linux 採用「等待圖檢測 + 超時機制 + 優先級繼承」緩解死鎖,而非純靜態預防。
死鎖雖是理論難題,但透過「資源有序分配」配合「超時重試」、「鎖層級設計」,工程上已能有效規避。理解原理,寫出不死鎖的高併發程式。