死锁,什么是死锁,怎么发现死锁

109 阅读2分钟

死锁,什么是死锁,怎么发现死锁

什么是死锁

死锁是发生在并发编程之中,多个线程在获取锁的过程之中发生阻塞,导致没有线程可以继续执行的情况。

例如线程t1先锁住了A对象,与此同时线程t2又锁住了B对象,而t1线程需要继续获取B对象的锁,t2线程需要继续获取A对象的锁,那么这个时候就会导致线程t1和t2同时发生阻塞,造成了死锁的现象。

image.png

@Slf4j
public class DeadLock {
    public static final Object A = new Object();
    public static final Object B = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (A){
                log.info("锁住了A");
                synchronized (B) {
                    log.info("锁住了B");
                }
            }
        },"t1").start();
        new Thread(() -> {
            synchronized (B){
                log.info("锁住了B");
                synchronized (A) {
                    log.info("锁住了A");
                }
            }
        },"t2").start();
    }
}

运行代码之后就发生了阻塞:

image.png 我们并不知道发生死锁的代码在哪里,那么我们怎么定位发生死锁的线程和代码位置呢?

发现死锁

这里使用IDEA进行演示。 打开IDEA之中的终端

使用jpsjstack

image.png 首先使用jps命令得到进程ID。找到与类名对应的进程ID

image.png 使用jstack命令加 进程ID 得到进程里运行的线程信息。

image.png 可以得到下面的信息

Found one Java-level deadlock:
=============================
"t1":
  waiting to lock monitor 0x00000183b3096b50 (object 0x0000000713dd89c0, a java.lang.Object),
  which is held by "t2"

"t2":
  waiting to lock monitor 0x00000183b3095030 (object 0x0000000713dd89b0, a java.lang.Object),
        at com.example.juc.DeadLock$$Lambda$28/0x000000080100f3d0.run(Unknown Source)
        at java.lang.Thread.run(java.base@17.0.7/Thread.java:833)
"t2":
        at com.example.juc.DeadLock.lambda$main$1(DeadLock.java:28)
        - waiting to lock <0x0000000713dd89b0> (a java.lang.Object)
        - locked <0x0000000713dd89c0> (a java.lang.Object)
        at com.example.juc.DeadLock$$Lambda$29/0x000000080100f5e8.run(Unknown Source)
        at java.lang.Thread.run(java.base@17.0.7/Thread.java:833)

Found 1 deadlock.

从信息之中,JVM帮我们发现了一个死锁,并指出了发生死锁的线程信息和发生死锁的代码位置。此时我们就定位到了发生死锁的位置。

使用jconsole的方式

JVM同样还为我们提供了图形化的方式来查看进程中线程的信息。同样在终端输入jconsole

image.png

选择对应的进程进入。 选择线程->检测死锁

image.png

此时jconsole就非常方便的帮我们得到了发生死锁的线程的信息。

image.png