分享Java死锁的4种排查工具

目录
  • 死锁示例
  • 死锁产生原因
  • 死锁排查
    • 方案 1:jstack
    • 方案 2:jconsole
    • 方案 3:jvisualvm
    • 方案 4:jmc
  • 总结

前言:

死锁(Dead Lock)指的是两个或两个以上的运算单元(进程、线程或协程),都在等待对方停止执行,以取得系统资源,但是没有一方提前退出,就称为死锁。

死锁示例

接下来,我们先来演示一下 Java 中最简单的死锁,我们创建两个锁和两个线程,让线程 1 先拥有锁 A,然后在 1s 后尝试获取锁 B,同时我们启动线程 2,让它先拥有锁 B,然后在 1s 之后尝试获取锁 A,这时就会出现相互等待对方释放锁的情况,从而造成死锁的问题,

具体代码如下:

public class DeadLockExample {
    public static void main(String[] args) {
        Object lockA = new Object(); // 创建锁 A
        Object lockB = new Object(); // 创建锁 B

        // 创建线程 1
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 先获取锁 A
                synchronized (lockA) {
                    System.out.println("线程 1:获取到锁 A!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 尝试获取锁 B
                    System.out.println("线程 1:等待获取 B...");
                    synchronized (lockB) {
                        System.out.println("线程 1:获取到锁 B!");
                    }
                }
            }
        });
        t1.start(); // 运行线程

        // 创建线程 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 先获取锁 B
                synchronized (lockB) {
                    System.out.println("线程 2:获取到锁 B!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 尝试获取锁 A
                    System.out.println("线程 2:等待获取 A...");
                    synchronized (lockA) {
                        System.out.println("线程 2:获取到锁 A!");
                    }
                }
            }
        });
        t2.start(); // 运行线程
    }
}

以上程序的执行结果如下: 

从上述结果可以看出,线程 1 和线程 2 都在等待对方释放锁,这样就造成了死锁问题。

死锁产生原因

通过以上示例,我们可以得出结论,要产生死锁需要满足以下 4 个条件

  • 互斥条件:指运算单元(进程、线程或协程)对所分配到的资源具有排它性,也就是说在一段时间内某个锁资源只能被一个运算单元所占用。
  • 请求和保持条件:指运算单元已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它运算单元占有,此时请求运算单元阻塞,但又对自己已获得的其它资源保持不放。
  • 不可剥夺条件:指运算单元已获得的资源,在未使用完之前,不能被剥夺。
  • 环路等待条件:指在发生死锁时,必然存在运算单元和资源的环形链,即运算单元正在等待另一个运算单元占用的资源,而对方又在等待自己占用的资源,从而造成环路等待的情况。

只有以上 4 个条件同时满足,才会造成死锁问题。

死锁排查

如果程序出现死锁问题,可通过以下 4 种方案中的任意一种进行分析和排查。

方案 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死锁的4种排查工具的文章就介绍到这了,更多相关Java死锁排查内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java项目有中多个线程如何查找死锁

    当项目有中多个线程,如何查找死锁? 最近,在IDEA上进行多线程编程中老是在给线程加锁的时候,总是会遇到死锁问题,而当程序出现死锁问题时,编译器不能精确的显示错误的精确位置.当项目代码很多的时候, 往往会给自己添加不必要的麻烦,今天,我就分享分享几个解决方法. 1.编译环境 IDEA 2020 ,windows10, jdk8及以上版本 一.死锁是什么? 死锁指A线程想使用资源但是被B线程占用了,B线程线程想使用资源被A线程占用了,导致程序无法继续下去了. 1.1 死锁的例子: public c

  • Java 死锁解决方案顺序锁和轮询锁

    目录 死锁解决方案分析 解决方案1:顺序锁 解决方案2:轮询锁 总结 前言: 死锁(Dead Lock)指的是两个或两个以上的运算单元(进程.线程或协程),都在等待对方停止执行,以取得系统资源,但是没有一方提前退出,就称为死锁. 死锁示例代码如下: public class DeadLockExample { public static void main(String[] args) { Object lockA = new Object(); // 创建锁 A Object lockB =

  • Java并发中死锁、活锁和饥饿是什么意思

    解答 死锁是指两个或者两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,他们将无法推进下去. 如果线程的智力不够, 且都秉承着"谦让"的原则,主动将资源释放给他人使用,那么就会导致资源不断地在两个线程间跳动,而没有一个线程可以同时拿到所有资源正常执行.这种情况就是活锁. 饥饿是指某一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行.比如它的线程优先级可能太低,而高优先级的线程不断抢占它需要的资源,导致低优先级线程无法工作.  补充

  • Java中死锁与活锁的具体实现

    目录 活锁与死锁 活锁 死锁 死锁的四个必要条件 互斥条件 请求和保持条件 不剥夺条件 环路等待条件 死锁示例 死锁排查 总结一下 如何避免死锁 预防死锁 设置加锁顺序 活锁示例 解决活锁 活锁与死锁 活锁 活锁同样会发生在多个相互协作的线程间,当他们为了彼此间的响应而相互礼让,使得没有一个线程能够继续前进,那么就发生了活锁.同死锁一样,发生活锁的线程无法继续执行. 相当于两个在半路相遇的人:出于礼貌他们相互礼让,避开对方的路,但是在另一条路上又相遇了.就这样,不停地一直避让下去.... 死锁

  • java定位死锁的三种方法(jstack、Arthas和Jvisualvm)

    目录 死锁 死锁发生的原因 死锁发生的条件 1:通过jstack定位死锁信息 1.2:查看死锁线程的pid 2:通过Arthas工具定位死锁 3. 通过 Jvisualvm 定位死锁 死锁的预防 总结 死锁 死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 死锁发生的原因 死锁的发生是由于资源竞争导致的,导致死锁的原因如下: 系统资源不足,如果系统资源充足,死锁出现的可能性就很低. 进程(线程)运行推进的顺序不合适. 资源分配

  • java并发编程死锁定义及如何避免死锁

    目录 场景模拟分析 场景一:狭路相逢 场景二:冷战 场景三:哲学家就餐 场景四:竞争资源 死锁是什么? 产生死锁的的四个条件如下: 如何避免死锁? 方案一:破坏不剥夺条件 方案二:破坏请求与保持条件 方案三:破坏循环等待条件 方案四:破坏互斥条件 场景模拟分析 场景一:狭路相逢 在星期天的早上十点半,你在公路上开着车,这是一条窄路,只能容纳一辆车.这时,迎面又驶来一辆车,你们都走到一半,谁也不想倒回去,于是各不相让.陷入无尽的等待. 场景二:冷战 你和她吵架了,谁也不理谁,甚至晚饭时间都各自煮饭

  • 分享Java死锁的4种排查工具

    目录 死锁示例 死锁产生原因 死锁排查 方案 1:jstack 方案 2:jconsole 方案 3:jvisualvm 方案 4:jmc 总结 前言: 死锁(Dead Lock)指的是两个或两个以上的运算单元(进程.线程或协程),都在等待对方停止执行,以取得系统资源,但是没有一方提前退出,就称为死锁. 死锁示例 接下来,我们先来演示一下 Java 中最简单的死锁,我们创建两个锁和两个线程,让线程 1 先拥有锁 A,然后在 1s 后尝试获取锁 B,同时我们启动线程 2,让它先拥有锁 B,然后在

  • 一篇文章学会java死锁与CPU 100%的排查

    目录 01 Java死锁排查和解决 1.啥是死锁? 2.为啥子会出现死锁? 3.怎么排查代码中出现了死锁?[重点来了] 第一个姿势:使用 jps + jstack 第二个姿势:使用jconsole 第三个姿势:使用Java Visual VM 4.如何避免死锁? 02.Java CPU 100% 排查技巧 第一个姿势,步骤有点多,难度四星 第二个姿势,待开发[奸笑脸] 03 推荐两个高效排查问题工具 04 总结 05 彩蛋-另一个姿势 00 本文简介 作为一名搞技术的程序猿或者是攻城狮,想必你应

  • 超详细的Java 问题排查工具单

    前言 平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了可快速翻阅,二是分享,希望看到此文的同学们可以拿出自己日常觉得帮助很大的工具,大家一起进步. 闲话不多说,开搞. Linux命令类 tail 最常用的tail -f tail -300f shopbase.log #倒数300行并进入实时监听文件写入模式 grep grep forest f.txt #文件查找 grep forest f.txt cpf.

  • 分享15款Java程序员必备的开发工具

    如果你是一名Web开发人员,那么用膝盖想也知道你的职业生涯大部分将使用Java而度过.这是一款商业级的编程语言,我们没有办法不接触它. 对于Java,有两种截然不同的观点:一种认为Java是最简单功能最强大的编程语言之一,另一种则表示这种编程语言既难用又复杂. 下面这些工具或许功能和作用不同,但是有着一个共同的主旨,那就是--它们都是为了给Java编码和开发提供卓越的支持. 1. JDK(Java开发工具包)如果你打算用Java开发一些小程序和应用程序,那么首先得给自己准备一个类似于JDK的工具

  • Java开发者推荐的10种常用工具

    以下是Java程序员在日常生活中最常用的10种工具.如果你正在使用Java,本文介绍将会对你有所帮助,如果你还不熟悉这些工具,在这里你可以对它们进行更加系统的了解. 1) IDE:Eclipse和NetBeans IDE是Java开发人员最为重要的工具.IDE不仅提供了集成的开发环境,还能够帮助导航.调试和记录代码.Eclipse作为行业领导者,有一半的Java开发人员都在使用它.而在编写测试程序.测试和调试Java web开发的新事物方面,我更推崇Netbeans,这是因为在web开发方面Ne

  • 分享Java多线程实现的四种方式

    目录 以下四种方式: 1.继承Thread类,重写run方法 2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target 3.通过Callable和FutureTask创建线程 4.通过线程池创建线程 后面两种可以归结成一类:有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中. 第一种:继承Thread类,重写该类的run()方法. class My

  • 浅谈java常用的几种线程池比较

    1. 为什么使用线程池 诸如 Web 服务器.数据库服务器.文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务.请求以某种方式到达服务器,这种方式可能是通过网络协议(例如 HTTP.FTP 或 POP).通过 JMS 队列或者可能通过轮询数据库.不管请求如何到达,服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的. 构建服务器应用程序的一个简单模型是:每当一个请求到达就创建一个新线程,然后在新线程中为请求服务.实际上对于原型开发这

  • Java实现的执行python脚本工具类示例【使用jython.jar】

    本文实例讲述了Java实现的执行python脚本工具类.分享给大家供大家参考,具体如下: 这里java中执行python脚本工具类,需要使用jython.jar java中执行python脚本工具类,学习的时候写着玩: import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; i

  • Java实现的进制转换工具类完整示例

    本文实例讲述了Java实现的进制转换工具类.分享给大家供大家参考,具体如下: import java.nio.charset.Charset; /** * 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15).<br> * 例如十进制数57,在二进制写作111001,在16进制写作39.<br> * 像java,c这样的语言为了区分十六进制和十进制数值,会在十六进制数的前面加上 0x,比如0x20是十进制的

  • Java设计模式之23种设计模式详解

    一.什么是设计模式 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是

随机推荐