Java 死锁
目錄:
一 什么是死鎖?
注:線程和進程都可能會產生死鎖,以下以線程為例
死鎖是指兩個或兩個以上的線程在執行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現象, 若無外力作用,它們都將無法推進下去。 此時稱系統處于死鎖狀態或系統產生了死鎖,這些永遠在互相等待的線程稱為死鎖線程。另一種定義:
集合中的每個線程都在等待只能由本集合內的其他線程才能引發的事件,那么該組線程是死鎖的。
競爭的資源可以是:鎖、網絡連接、通知事件,磁盤、帶寬,以及一切可以被稱作“資源”的東西。
二 死鎖是怎么產生的?
死鎖的主要產生原因:
產生死鎖的四個必要條件:
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會產生死鎖
常見死鎖:
避免死鎖的一個通用的經驗法則是
當多個線程都要訪問資源A、B、C時,保證使每個線程都按照同樣的順序去訪問它們,
即:讓所有線程按照同樣的順序獲得一組鎖;
三、怎么排查死鎖
首先,編寫一個死鎖程序:
public static void main(String[] args) {final Object a = new Object();final Object b = new Object();Thread threadA = new Thread(new Runnable() {public void run() {synchronized (a) {try {System.out.println("now i in threadA-locka");Thread.sleep(1000l);synchronized (b) {System.out.println("now i in threadA-lockb");}} catch (Exception e) {// ignore}}}});Thread threadB = new Thread(new Runnable() {public void run() {synchronized (b) {try {System.out.println("now i in threadB-lockb");Thread.sleep(1000l);synchronized (a) {System.out.println("now i in threadB-locka");}} catch (Exception e) {// ignore}}}});threadA.start();threadB.start();}上面的代碼執行后,就會出現死鎖,排查方法如下:
方式1:使用jps + jstack
第一:在windons命令窗口,使用 jps -l 第二:在windons命令窗口,使用 jstack -l 9004
死鎖信息如上圖,結合代碼看就可以找出原因了。
方式2:使用jconsole
在window打開 JConsole,JConsole是一個圖形化的監控工具
四、死鎖預防:
遇見問題,解決問題是一般人的思維。高手都是提前預見問題,并有效預防。
死鎖的常見預防思路如下:
當使用synchronized關鍵字提供的內置鎖時,只要線程沒有獲得鎖,就會永遠等待下去。
然而Lock接口提供了:
該方法可以按照固定時間等待鎖,所以線程可以在獲取鎖超時時,主動釋放之前已經獲得的所有的鎖。
五、拓展:
Java CPU 100%排查
見:https://blog.csdn.net/u010648555/article/details/80721815
總結
- 上一篇: Federation 简介
- 下一篇: Java 锁之 CAS