什么是死锁
死锁(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:文章来源:https://www.toymoban.com/news/detail-436466.html
以上是jdk8以上版本排查线程死锁的常用三种方案,还有一种是根据jmc(Oracle Java Mission Control )排查,jmc是一个对 Java 程序进行管理、监控、概要分析和故障排查的工具套件,它也是在 JDK 的 bin 目录中。但是jdk1.8之后,jmc就已经不随着jdk一起发出去了,如果想要使用jmc对jvm进行监控,这时候需要手工下载jmc,然后在本地运行。oracle官网比较坑,现在只有jmc8.1版本下载,它需要jdk11,但作者暂时还没亲自试过,所以先不写了。文章来源地址https://www.toymoban.com/news/detail-436466.html
到了这里,关于死锁检测的常用3种方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!