用jstack定位死锁

死锁示例代码

public class TestMain implements Runnable {

    //定义两把锁
    static Object lock1 = new Object();
    static Object lock2 = new Object();
    //定义一个标志位,方便执行不同逻辑
    int flag;

    @Override
    public void run() {
        if (flag == 1) {
            synchronized (lock1) {
                System.out.println(Thread.currentThread().getName() + "获取到了lock1");
                System.out.println(Thread.currentThread().getName() + "等待获取lock2");
                try {
                    //睡眠500毫秒,确保线程二已经拿到了lock2
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println(Thread.currentThread().getName() + "获取到了lock2");
                }
            }
            System.out.println(Thread.currentThread().getName() + "运行结束");
        }
        if (flag == 2) {
            synchronized (lock2) {
                System.out.println(Thread.currentThread().getName() + "获取到了lock2");
                System.out.println(Thread.currentThread().getName() + "等待获取lock1");
                try {
                    //睡眠500毫秒,确保线程一已经拿到了lock1
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.println(Thread.currentThread().getName() + "获取到了lock1");
                }
            }
            System.out.println(Thread.currentThread().getName() + "运行结束");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestMain testMain1 = new TestMain();
        testMain1.flag = 1;
        Thread thread = new Thread(testMain1, "线程一");
        TestMain testMain2 = new TestMain();
        testMain2.flag = 2;
        Thread thread1 = new Thread(testMain2, "线程二");
        thread.start();
        thread1.start();
    }
}

定位死锁的步骤

  • 用工具或者命令行,比如top,定义java进程的pid
  • 然后使用【${JAVA_HOME}/bin/jstack pid】 的命令查看具体情况

会出现如下结果:

在这里插入图片描述
可以清晰的看到出现问题的行数,以及线程一和线程二当前持有的锁和正在等待的锁是哪个。

总结

会出现死锁,肯定是代码逻辑出现了问题,这里只是分享一个定位死锁的方法,而如果生产环境出现了问题,是不可能先花时间去排查的,要先保证生产的可用,然后把出现死锁的信息保存下来,后面再排查和修改相应代码,当然了,最好的解决死锁方法就是避免死锁情况的出现。

发布了242 篇原创文章 · 获赞 250 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_38106322/article/details/104648032