Java線程死鎖查看分析方法


如何查看是否有Java線程死鎖?下面介紹兩種方法。

一.Jconsole
        Jconsole是JDK自帶的圖形化界面工具,使用JDK給我們的的工具JConsole,可以通過打開cmd然后輸入jconsole打開。


        連接到需要查看的進程。

        打開線程選項卡,然后點擊左下角的“檢測死鎖” 。


        jconsole就會給我們檢測出該線程中造成死鎖的線程,點擊選中即可查看詳情:


從上圖中我們可以看出:

        在線程Thread-1中,從狀態可以看出,它想申請java.lang.Object@35b4e829這個資源,但是這個資源已經被Thread-0擁有了,所以就堵塞了。

        在線程Thread-0中,從狀態可以看出,它想申請java.lang.Object@2db8dc9這個資源,但是這個資源已經被Thread-1擁有了,所以就堵塞了。

        Thread-1一直等待java.lang.Object@35b4e829資源,而Thread–0一直等待java.lang.Object@2db8dc9資源,於是這兩個線程就這么僵持了下去,造成了死鎖。

 

二.Jstack

        Jstack是JDK自帶的命令行工具,主要用於線程Dump分析。

        1.我們先用Jps來查看java進程id(或者Linux的ps命令)


        2.看一下jstack的使用

        3.jstack輸出線程dump信息到文件

        用比較工程查看帶-l和不帶-l的區別如下:


        4.查看dump文件,然后進行分析

        其中有一行是at DeadThread.run(DeadThread.java:37),說明Thread-1實在DeadThread類的37行處發生死鎖,其中at DeadThread.run(DeadThread.java:21),說明Thread-0是在DeadThread類的21行處發生死鎖。詳細的jstack dump文件分析請參看:http://www.cnblogs.com/flyingeagle/articles/6853454.html

        從而定位到死鎖發生的原因,及具體位置:Thread-0獲得了鎖lock1,接下來期望獲得鎖lock2,(第20行),但是此時Thread-1獲得了鎖lock2,接下來期望獲得鎖lock2,(第37行),因而發生了死鎖。

 

附實例DeadThread.java代碼:

public class DeadThread implements Runnable {

    public String username;
    public Object lock1 = new Object();
    public Object lock2 = new Object();

    @Override
    public void run() {
        // TODO Auto-generated method stub  
        if (username.equals("a")) {
            synchronized (lock1) {
                try {
                    System.out.println("username = " + username);
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(3000);
                } catch (Exception e) {
                    // TODO: handle exception  
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println("按lock1->lock2的順序執行代碼");
                }
            }
        }
        if (username.equals("b")) {
            synchronized (lock2) {
                try {
                    System.out.println("username = " + username);
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(3000);

                } catch (Exception e) {
                    // TODO: handle exception  
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.println("按lock2->lock1順序執行代碼");
                }
            }

        }
    }

    public void setFlag(String username) {
        this.username = username;
    }
    
    public static void main(String[] args) {

        DeadThread dt1 = new DeadThread();
        dt1.setFlag("a");
        Thread t1 = new Thread(dt1);
        t1.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        dt1.setFlag("b");
        Thread t2 = new Thread(dt1);

        t2.start();
    }
}

 

文章來源:http://blog.csdn.net/abc86319253/article/details/49534225

http://blog.csdn.net/lu__peng/article/details/52822632#


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM