你真的理解什麼是死鎖嗎?

一. 死鎖的概念

兩個或多個進程,因爲資源的競爭或者彼此間的通訊而形成的阻塞現象,若是沒有外力干預,它們將沒法進行下去,這就發生了死鎖。算法

更規範的定義:集合中的每個進程都在等待只能由本集合中的其餘進程才能引起的事件(資源),那麼該組進程是死鎖的。安全

上面說到的競爭的資源能夠是一切能稱爲資源的東西,好比鎖,網絡鏈接,通知事件,磁盤等網絡

舉個例子

比方說有兩個線程,a 和 b工具

  • a 線程持有鎖 a,等待鎖 b
  • b 線程持有鎖 b,等待鎖 a

這樣這兩個線程就出現了死鎖線程

二. 產生死鎖的必要條件

  • 互斥條件:一個資源一次只能被一個進程訪問;一旦分配給某個進程,其餘進程就不能再訪問(由於競爭資源的被佔用是發生死鎖的一個重要緣由)
  • 請求和保持條件:進程在等待其餘線程佔用的資源(請求),與此同時,進程會一直佔用着本身已經得到的資源(保持)
  • 不可剝奪條件:進程對於已經申請到的資源在使用完成以前不能夠被剝奪(也就是不會被其餘進程搶走本身的資源)
  • 環路等待條件:發生死鎖的進程組中,每個進程都會佔有另外一個進程所須要的資源,這個佔有關係能夠造成一個等待環路(也就是競爭資源被相互佔用,沒法找到突破口,只能被死死堵着)

三. 如何預防和避免死鎖

1. 以特定的順序獲取資源

以上面的例子來講,A 線程先嚐試獲取 a 鎖再嘗試獲取 b 鎖;而 B 線程則相反。這樣子的設計就極可能出現死鎖。設計

若是一組線程都按照一樣的順序來嘗試得到鎖,那麼就能夠避免死鎖的發生了。3d

2. 超時放棄

設置佔有資源或者佔有鎖的最大時間,若是超過該時間仍未釋放,那麼就主動釋放該資源cdn

3. 預先分配資源

在進程運行以前一次性的將其所需(申請)的資源分配給他,保證其能夠正常的執行完畢,不須要在進程運行時再申請資源。blog

該方法的弊端體如今資源利用率低的方面,由於並非全部的資源在進程運行時都會被長時間佔用,可是這樣在運行前一次性分配的方式會形成全部資源在該進程的生命週期內都是不能夠被釋放的。生命週期

4. 銀行家算法

銀行家算法是一種直接避免死鎖的方式,主要的思想就是動態檢查進程對資源的申請,以檢查是否會形成死鎖。

咱們經過列出各個線程(進程)的當前佔有的資源,最大所須要的資源以及當前剩餘的可利用資源,能夠計算可得知當前是否爲安全狀態(也就是必定不會發生死鎖),簡單來講就是確保當前能夠利用的資源是充足的

四. 檢測死鎖

若是咱們不去主動預防或者避免死鎖,那麼咱們能夠經過及時檢測當前是否出現死鎖的方式來處理死鎖問題,好比使用一些死鎖檢測算法

而何時去進行死鎖檢測又取決於死鎖發生的頻率以及通常狀況下死鎖涉及的進程數;這樣,咱們既能夠選擇定時檢測,也能夠在發現資源利用率降低時進行檢測,總之,你得知道發生死鎖時,你的程序會有怎樣的變化。

監控工具 JConsole

JDK 也自帶了一個監控工具 JConsole,在JDK/bin目錄下能夠找到。

鏈接本地進程:

查詢是否存在死鎖:

五. 解除死鎖

當發生了死鎖以後,咱們確定要去解決掉它的。最直接的方法確定是重啓,固然不少時候這樣作不太可取。

  • 終止相關進程:檢測出與死鎖有關的進程,撤銷或者掛起它,強制它釋放資源
  • 剝奪資源:將部分被死鎖進程佔用的資源剝奪出來,解除死鎖
  • 進程回退:將死鎖進程回退到未出問題以前,不過實現難度較大。
相關文章
相關標籤/搜索