1. 程式人生 > 其它 >面試突擊48:死鎖的排查工具有哪些?

面試突擊48:死鎖的排查工具有哪些?

死鎖(Dead Lock)指的是兩個或兩個以上的運算單元(程序、執行緒或協程),都在等待對方釋放資源,但沒有一方提起釋放資源,從而造成了一種阻塞的現象就稱為死鎖。

比如執行緒 1 擁有了鎖 A 的情況下試圖獲取鎖 B,而執行緒 2 又在擁有了鎖 B 的情況下試圖獲取鎖 A,這樣雙方就進入相互阻塞等待的情況,如下圖所示:

死鎖的程式碼實現如下:

import java.util.concurrent.TimeUnit;

public class DeadLockTest {
    public static void main(String[] args) {
        Object lockA = new Object();
        Object lockB = new Object();
        // 建立執行緒 1
        Thread t1 = new Thread(() -> {
            // 1.佔有鎖 A
            synchronized (lockA) {
                System.out.println("執行緒1:獲得鎖A。");
                // 休眠 1s(讓執行緒 2 有時間先佔有鎖 B)
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 2.獲取執行緒 2 的鎖 B
                synchronized (lockB) {
                    System.out.println("執行緒1:獲得鎖B。");
                }
            }
        });
        t1.start();
        // 建立執行緒 2
        Thread t2 = new Thread(() -> {
            // 1.佔有鎖 B
            synchronized (lockB) {
                System.out.println("執行緒2:獲得鎖B。");
                // 休眠 1s(保證執行緒 1 能有充足的時間得到鎖 A)
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 2.獲取執行緒 1 的鎖 A
                synchronized (lockA) {
                    System.out.println("執行緒2:獲得鎖A。");
                }
            }
        });
        t2.start();
    }
}

以上程式的執行結果如下圖所示:

從上述結果可以看出,執行緒 1 和執行緒 2 都在等待對方釋放鎖,這樣就造成了死鎖問題。
哪死鎖應該如何排查呢?

死鎖的排查工具

排查死鎖總共有 4 種工具:

  1. jstack
  2. jconsole
  3. jvisualvm
  4. jmc

接下來,我們一一來看。

排查工具 1:jstack

在使用 jstack 之前,先要通過 jps 得到執行程式的程序 ID,使用方法如下:

“jps -l”可以查詢本機所有的 Java 程式,jps(Java Virtual Machine Process Status Tool)是 Java 提供的一個顯示當前所有 Java 程序 pid 的命令,適合在 linux/unix/windows 平臺上簡單檢視當前 Java 程序的一些簡單情況,“-l”用於輸出程序 pid 和執行程式完整路徑名(包名和類名)。

有了程序 ID(PID)之後,我們就可以使用“jstack -l PID”來發現死鎖問題了,如下圖所示:

jstack 用於生成 Java 虛擬機器當前時刻的執行緒快照,“-l”表示長列表(long),列印關於鎖的附加資訊。

PS:可以使用 jstack -help 檢視更多命令使用說明。

排查工具 2:jconsole

使用 jconsole 需要開啟 JDK 的 bin 目錄,找到 jconsole 並雙擊開啟,如下圖所示:

然後選擇要除錯的程式,如下圖所示:

之後點選連線進入,選擇“不安全的連線”進入監控主頁,如下圖所示:


之後切換到“執行緒”模組,點選“檢測死鎖”按鈕,如下圖所示:

之後稍等片刻就會檢測出死鎖的相關資訊,如下圖所示:

排查工具 3:jvisualvm

jvisualvm 也在 JDK 的 bin 目錄中,同樣是雙擊開啟:

稍等幾秒之後,jvisualvm 中就會出現本地的所有 Java 程式,如下圖所示:

雙擊選擇要除錯的程式:

單擊滑鼠進入“執行緒”模組,如下圖所示:

從上圖可以看出,當我們切換到執行緒一欄之後就會直接顯示出死鎖資訊,之後點選“執行緒 Dump”生成死鎖的詳情資訊,如下圖所示:

排查工具 4:jmc

jmc 是 Oracle Java Mission Control 的縮寫,是一個對 Java 程式進行管理、監控、概要分析和故障排查的工具套件。它也是在 JDK 的 bin 目錄中,同樣是雙擊啟動,如下圖所示:

jmc 主頁資訊如下:

之後選中要排查的程式,右鍵“啟動 JMX 控制檯”檢視此程式的詳細內容,如下圖所示:


然後點選“執行緒”,勾中“死鎖檢測”就可以發現死鎖和死鎖的詳情資訊,如下圖所示:

總結

死鎖的排查工具總共有 4 種:jstack、jconsole、jvisualvm、jmc,從易用性和效能方面來考慮,推薦使用 jconsole 或 jvisualvm 來排查死鎖。

是非審之於己,譭譽聽之於人,得失安之於數。

公眾號:Java面試真題解析
面試合集:https://gitee.com/mydb/interview