文章目錄
1. 死鎖的概念
1.1 哲學家就餐問題
問題描述:五個哲學家圍坐在圓桌邊,有5支筷子。他們做的事就是:思考-休息-吃飯
吃飯時使用兩支筷子:
- 拿一雙筷子才能吃飯
- 每次只能取一支筷子
- 只取身邊的筷子
- 吃完放下筷子
用線程實現哲學家的生活,如下僞代碼所示:
int signal[5] = [1, 1, 1, 1, 1]; //筷子i是否可用:0=不可用;1=可用
Philosopher (int i)
{
while(TRUE){
思考;
休息;
P(signal[i]); //取左邊的筷子;
P(signal[(i+4)%5]); //取右邊的筷子;
吃飯;
V(signal[(i+4)%5]); //放下右邊的筷子;
V(signal[i]); //放下左邊的筷子;
放下右邊的筷子;
放下左邊的筷子;
}
}
假如5個哲學家在同一時刻吃飯,大家都拿起了左邊的筷子,但是右邊的筷子沒有,所有人都在等待右邊人放下手中的筷子。而右邊的人沒有吃完之前又不會放下筷子,所以所有的人都缺一支筷子永遠無法吃完飯,這時候就陷入了死鎖
。
1.2 死鎖定義
兩個或多個進程無限期地等待永遠不會發生的條件的一種系統狀態。其結果就是每個進程都永遠阻塞。
另一種定義:在兩個或多個進程中,每個進程都持有某種資源,但又繼續申請其他的進程已持有的資源,此時每個進程都擁有其運行所需的一部分資源,但是又都不夠,從而每個進程都無法向前推進,限於阻塞狀態。這種狀態稱爲死鎖。
2. 死鎖的起因
- 系統資源有限:資源的數目不足,進程對資源競爭導致死鎖
- 併發程序的推進順序不當:進程請求資源和釋放資源的順序不當,導致死鎖
- 不正當的P-V操作也可能會帶來死鎖
2.1 死鎖的一些結論
- 參與死鎖的進程至少是兩個
- 參與死鎖的進程至少有兩個已經佔有資源
- 參與死鎖的所有進程都在等待資源
- 參與死鎖的進程是當前系統中所有進程的子集
- 死鎖會浪費大量的系統資源,甚至導致系統崩潰
3. 死鎖的預防策略
3.1 死鎖的必要條件
條件 | 描述 |
---|---|
互斥條件 | 進程互斥使用資源,資源具有獨佔性 |
不剝奪條件 | 進程在訪問完資源前不能被其他進程強行剝奪 |
部分分配條件 | 進程邊運行邊申請資源,臨時需要臨時分配 |
環路條件 | 多個進程構成環路:環中每個進程已佔用的資源前一進程所示,而自己所申請的資源又被環中後已進程佔用着 |
上面討論的哲學家吃飯問題,如果限定最多隻有4人同時吃飯,就可以避免死鎖。因爲此時環路條件被破壞了。
3.2 解決死鎖策略
通過設置某些限制條件,破壞死鎖的四個必要條件中的一個或多個來防止死鎖.
- 破壞互斥條件(難)
- 破壞不剝奪條件(代價大)
- 破壞部分分配條件(預先靜態分配)
- 破壞環路條件(有序資源分配)
3.2.1 預先靜態分配法
進程運行前將所需資源一次性全部分配給它。因此進程在運行的過程中不再提出資源請求,從而避免出現阻塞或死鎖。
特點:
- 執行可能被延遲
- 應用開銷大:運算前要估算資源請求
- 資源利用率低:資源被佔用而不用
改進:
- 資源分配的單位油由進程改爲程序步
3.2.2 有序資源分配法
系統中的每個資源有一個唯一序號,進程每次申請資源時只能申請序號更大的資源。如果進程已佔有資源的信號最大爲M,則下次申請只能申請大於M的資源,而不能申請序號小於M的資源。
實行過程:
- 分配資源時檢查是否符合遞增規定
- 若不符合,在拒絕申請,並撤銷該進程
- 若符合,且資源可用則予以分配。若資源不可能則不分配,陷於阻塞
3.3 Windows和Linux採取的措施
鴕鳥策略
- 不管死鎖,選擇相信開發人員。不採取任何措施。