【操作系統】死鎖

【操作系統】線程同步、線程互斥、原子操作 一問中,使用到了 這個東西,當一個線程進入臨界區後把門鎖起來,其他線程跑到這裏來發現鎖被使用了,就等着鎖被釋放。
當然,這是理想的情況下,但實際開發中還會出現下面的情況。

死鎖栗子

mutex;   //代表一個全局互斥對象

void  A() {
    mutex.lock();

    //這裏操作共享數據

    B();
    mutex.unlock();
    return;
}

void  B()
{
    mutex.lock();

    //這裏操作共享數據

    mutex.unlock();
    return;
}

可別想的是自己寫不出這樣的代碼來,哈哈哈。

死鎖概念

死鎖是指在一組進程中的各個線程均佔有不會釋放的資源,但因互相申請被其他進程所站用不會釋放的 資源而處於的一種永久等待狀態。

產生死鎖的 4 個必要條件

1、互斥條件:一個資源每次只能被一個執行流使用。
2、請求與保持條件:一個執行流因請求資源而阻塞時,對已獲得的資源保持不放。
3、不剝奪條件:一個執行流已獲得的資源,在末使用完之前,不能強行剝奪。
4、循環等待條件:若干執行流之間形成一種頭尾相接的循環等待資源的關係。

常見場景

1、一個線程加鎖後再次嘗試加鎖。
2、兩個線程 t1, t2 有兩把鎖 m1, m2,線程 t1 先去獲取鎖 m1 再去獲取鎖 m2,線程 t2 先去獲取鎖 m2 再去獲取鎖 m1,造成死鎖。
3、多個線程多個鎖。哲學家就餐問題!

哲學家就餐問題

哲學家就餐問題: 比如5個哲學家和五根筷子。

哲學家行爲:1. 思考(啥都不幹) 2. 喫雞

極端情況,五個哲學家同時拿起自己左手邊的筷子,然後哲學家就無法再拿起右手的筷子。
那麼當所有哲學家都不願意放下左手的筷子,就會造成所有線程死鎖。

解決方法:
方法1
做出約定:先給每個筷子編號,約定哲學家每次先拿編號小的筷子。若所有哲學家依次拿筷子,到最後的哲學家肯定就會拿另一根筷子,就可以避免出現死鎖。這樣的順序約定是破除死鎖的常見辦法。破除死鎖中的"環路等待"條件。
比如現在我給每個筷子給上編號,當一號哲學家拿的時候先拿1號筷子,二號哲學家先拿2號筷子。。以此類推當五號哲學家拿筷子的時候,不會再去拿5號筷子了,而是嘗試去拿1號筷子,但是1號筷子已經被一號哲學家拿過了,所以五號哲學家就需要等待。四號哲學家就可以再拿5號筷子可以喫飯了,等他喫完釋放4 5 號筷子,3號哲學家就可以喫飯了。。以此類推。這樣就解決了。

方法2
信號量 PV 操作。
搞一個信號量初始化爲 4(比鎖數量少 1)
每個哲學家拿筷子的時候進行 P 操作,當第 5 個人在申請鎖的時候信號量爲 0 就不可以申請了。

如何避免死鎖

1、破壞死鎖的 4 個條件。
2、加鎖順序一致。
3、避免鎖未釋放。
4、資源一次性分配。
5、算法(死鎖檢測算法、銀行家算法)。


參考文章:
https://blog.csdn.net/weixin_42678507/article/details/90906296

更多:
C++ 死鎖案例:
https://blog.csdn.net/i_likechard/article/details/78206018

EOF

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章