死鎖的產生及處理策略條件
死鎖
什麼是死鎖?
我們先從互斥量造成的死鎖說起。
當一個執行緒去申請一個已經被持有,但是還沒有釋放的互斥量時,執行緒將會被阻塞,直到該互斥量被釋放。如果該互斥量不被釋放,該執行緒將會被一直阻塞。
因次,基於以上的原因,我們可以認為當一個執行緒去申請一個永遠不會被釋放的互斥量時,該執行緒將會被永遠阻塞,這種情景我們稱之為死鎖。更寬泛的說,死鎖就是,一個執行緒阻塞的等待一個永遠不會為真的條件。
以下為兩個常見的互斥量中死鎖場景
(1)當一個執行緒重複的拿取同一個互斥量
當一個執行緒申請到該互斥量後,在持有該互斥量的同時,再次申請該互斥量。而此時,因為該互斥量已經被它自身持有,再次申請時,該執行緒將會被阻塞。但是改互斥量必須被被它自身釋放後,才能繼續被申請。但此時,執行緒被阻塞,將永遠無法釋放鎖,並再次申請。所以該執行緒將會被永遠阻塞。這種場景會出現在,在一個函式的內部存在對鎖的申請,當一個執行緒呼叫該函式申請到鎖後,在鎖的內部再次呼叫該函式,就會出現該執行緒對一個互斥量同時申請兩次。
(2)當兩個執行緒,對兩個互斥量以相反的順序進行相互持有
假如有兩個執行緒 A B ,有兩個 互斥量 1 和 2,執行緒A先申請2鎖 ,執行緒B先申請1鎖,當執行緒A申請完2 後,在持有2的同時去申請1,當執行緒B申請完1後,在持有1的同時去申請2.但是此時,雙方都去申請對方的鎖,但是鎖被對方持有,所以兩個執行緒只能阻塞等待,在陷入阻塞後,雙方持有的鎖都將無法釋放,所以兩個執行緒將會永遠的阻塞。從而造成死鎖。
以上兩種場景是在互斥量的條件下,常見的死鎖場景,但是這兩種造成死鎖的場景,並不侷限於互斥量,只要滿足產生死鎖的條件,就會出現死鎖。
前人總結了產生了死鎖的四個必要條件:
- 互斥條件。
與鎖一樣,要麼能被申請,要麼就只能等待。在任意時刻,某份資源只能被一個程序或執行緒使用。
- 佔有和等待條件。
是指某個執行緒或程序,在佔有某份資源後還可以申請其他的資源。
- 不可搶佔條件。
當某份資源被某一程序或執行緒佔有時,不能被其他執行緒或程序強制性的搶佔,只能被佔有它的執行緒主動的釋放。
- 環路等待條件。
死鎖發生時,系統中一定有兩個或兩個以上的程序組成的一條環路,該環路中的每一個執行緒或程序都在等待下一個程序所佔用的資源。
以上的四個條件必須同時滿足,才會可能造成死鎖。只要有一個條件不滿足,就不會造成死鎖。
死鎖的產生並不僅會只有互斥量時會發生,只要滿足以上四個條件即可。在系統中,有許多隻能被互斥性訪問的獨佔資源,如請求獨佔性的io裝置,印表機等,在對其進行操作時,也有可能造成死鎖。
處理死鎖的四種策略
(1)忽略該問題。
把死鎖忽略,不注意死鎖。有的死鎖產生的時間並不確定。而且死鎖發生的頻度,造成問題的嚴重性不同。假如對於一個死鎖每隔幾個月或者每個幾年出現一次,而且每次造成的問題並不嚴重,那麼此時,工程師可能並不會以損失可用性或效能損失的代價去防止死鎖。此種情況下就屬於忽略死鎖的問題。
(2)檢測死鎖並恢復。
當出現死鎖時,通過檢測死鎖的技術,檢測到出現的死鎖,對於找到的死鎖進行恢復。