什么是死锁 死锁(Dead Lock)是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
死锁(Dead Lock)是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
接下来,我们先来演示一下 Java 中最简单的死锁,我们创建两个锁和两个线程,让线程 1 先拥有锁 o1,然后在 2s 后尝试获取锁 o2,同时我们启动线程 2,让它先拥有锁 o2,然后在 2s 之后尝试获取锁 o1,这时就会出现相互等待对方释放锁的情况,从而造成死锁的问题。
具体代码如下:
public class DeadLock { public static void main(String[] args) { Thread thread1 = new Thread(new DeadLockDemo(true)); Thread thread2 = new Thread(new DeadLockDemo(false)); thread1.start(); thread2.start(); }}class DeadLockDemo implements Runnable { static Object o1 = new Object(); static Object o2 = new Object(); boolean flag; public DeadLockDemo(boolean flag) { this.flag = flag; } @Override public void run() { if (flag) { synchronized (o1) { System.out.println("线程1进入o1"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1等待进入o2"); synchronized (o2) { System.out.println(Thread.currentThread().getName() + "线程进入o2"); } } } else { synchronized (o2) { System.out.println("线程2进入o2"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程2等待进入o1"); synchronized (o1) { System.out.println(Thread.currentThread().getName() + "线程进入o1"); } } } }}
程序执行结果:
从上述结果可以看出,线程 1 和线程 2 都在等待对方释放锁,这样就造成了死锁问题。
通过以上示例,我们可以得出结论,要产生死锁需要满足以下 4 个条件:
互斥条件:指运算单元(进程、线程或协程)对所分配到的资源具有排它性,也就是说在一段时间内某个锁资源只能被一个运算单元所占用。
请求和保持条件:指运算单元已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它运算单元占有,此时请求运算单元阻塞,但又对自己已获得的其它资源保持不放。
不可剥夺条件:指运算单元已获得的资源,在未使用完之前,不能被剥夺。
环路等待条件:指在发生死锁时,必然存在运算单元和资源的环形链,即运算单元正在等待另一个运算单元占用的资源,而对方又在等待自己占用的资源,从而造成环路等待的情况。
只有以上 4 个条件同时满足,才会造成死锁问题。
如果程序出现死锁问题,可通过以下 3种方案中的任意一种进行分析和排查。
方案一:jstack
在使用 jstack 之前,我们需要先通过 jps -l得到运行程序的进程 ID,使用方法如下:
有了进程 ID(PID)之后,我们就可以使用“jstack -l PID”来发现死锁问题了,如下图所示:
方案二:jconsole
jconsole工具位于jdk的bin目录下,如图:
双击进入,选择要调试的程序,如下图所示:
会出现如下提示,选择不安全的链接
点击线程栏目,然后点下面死锁,就会检测出来了
方案三:jvisualvm
jvisualvm 也在 JDK 的 bin 目录中,同样是双击打开:
点击线程栏目,如果发生死锁,会自动提示如下:
点击线程dump:
以上是jdk8以上版本排查线程死锁的常用三种方案,还有一种是根据jmc(oracle Java Mission Control )排查,jmc是一个对 Java 程序进行管理、监控、概要分析和故障排查的工具套件,它也是在 JDK 的 bin 目录中。但是jdk1.8之后,jmc就已经不随着jdk一起发出去了,如果想要使用jmc对JVM进行监控,这时候需要手工下载jmc,然后在本地运行。oracle官网比较坑,现在只有jmc8.1版本下载,它需要jdk11,但作者暂时还没亲自试过,所以先不写了。
来源地址:https://blog.csdn.net/qq_38860250/article/details/128713910
--结束END--
本文标题: 死锁检测的常用3种方法
本文链接: https://lsjlt.com/news/375779.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0