zoukankan      html  css  js  c++  java
  • 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();
        }
    }
    复制代码
  • 相关阅读:
    eclipse下c/cpp " undefined reference to " or "launch failed binary not found"问题
    blockdev 设置文件预读大小
    宝宝语录
    CentOS修改主机名(hostname)
    subprocess报No such file or directory
    用ldap方式访问AD域的的错误解释
    英特尔的VTd技术是什么?
    This virtual machine requires the VMware keyboard support driver which is not installed
    Linux内核的文件预读详细详解
    UNP总结 Chapter 26~29 线程、IP选项、原始套接字、数据链路访问
  • 原文地址:https://www.cnblogs.com/lianghe01/p/8227860.html
Copyright © 2011-2022 走看看