目錄
引入
死鎖
概念
示例
多把鎖
單鎖
4個必要條件?
用途?
引入
我們用加鎖的方式保證了多個線程訪問臨界資源時,不會出現數據紊亂的問題
但是,鎖的引入,會導致出現其他的問題
死鎖
概念
- 在多線程或多進程的并發環境中,兩個或多個進程或線程被永久阻塞,因為它們在等待對方釋放資源,而自己卻不釋放已經占有的資源
- 進程或線程無法繼續執行,而無法自行解除阻塞
示例
多把鎖
一個線程可以申請多把鎖:
- 線程A申請了a鎖,線程B申請了b鎖
- 但在兩個線程釋放鎖之前,線程A又需要b鎖(也就是需要訪問b鎖范圍內的臨界區代碼),那么A就會等待b鎖的釋放
- 但是此時,如果線程B需要用a鎖,就會形成死鎖了
- 因為a鎖還正在被線程A持有,線程B需要等待a鎖的釋放
- 于是,這兩個線程就互相等待對方釋放鎖,但都處于掛起狀態,而鎖是無法自己釋放的,所以他倆只能一直這么等下去
單鎖
如果只需要一把鎖,也可能會出現死鎖問題(當然,這是特殊情況)
- 如果一個線程已經申請了a鎖,在釋放鎖之前,它又不小心申請了鎖 / 把釋放鎖的函數名unlock寫成了lock,就會形成死鎖
- 因為鎖已經被持有(雖然這個人是自己),但是lock函數的第一句就是將al賦為0,所以自己持有的狀態并不影響lock的執行
- 他依然會用內存中mutex的0和al的0交換,然后判斷失敗被掛起
- 掛起后,線程帶走自己的上下文數據,也就是al中的0
- 這樣,鎖就丟失了,線程永遠也無法等待到鎖
4個必要條件?
互斥條件
- 一個資源每次只能被一個執行流使用
- (這是基礎條件,我們只有使用了互斥鎖,才會出現死鎖問題)
請求與保持條件
- 一個執行流因請求資源而阻塞時,對已獲得的資源保持不放
- (也就是既要又要,他不會放棄自己的,又會向別人索要)
不剝奪條件
- 一個執行流已獲得的資源,在末使用完之前,不能強行剝奪
- (他雖然向別人索要,但只是一種請求,不會也不能強制拿取)
循環等待條件
- ???????若干執行流之間形成一種頭尾相接的循環等待資源的關系
- 也就是說,申請資源的方向要形成環
用途?
因為是必要條件,所以只要這四個條件之一不滿足,即可避免死鎖問題
比如:
- 我們只有在必要時才使用鎖,并且要將鎖的范圍盡可能的縮小
- 在申請別人的資源不成功若干次后,可以考慮先釋放掉自己的鎖(萬一對方就是在等這個鎖呢)
- 盡量在一個鎖范圍內完成對共享資源的處理,避免出現多個鎖 / 嚴格控制每個線程申請鎖的順序