死锁是什么

死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉那它们都将无法推进下去,如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。

死锁示例

产生死锁的原因

  • 系统资源不足
  • 进程运行推进的顺序不合适
  • 资源分配不当

死锁代码示例

public class DeadLockDemo {
    static  Object a=new Object();
    static  Object b=new Object();
 
    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (a){
                System.out.println("t1线程持有a锁,试图获取b锁");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (b){
                    System.out.println("t1线程获取到b锁");
                }
            }
         },"t1").start();
 
        new Thread(() -> {
            synchronized (b){
                System.out.println("t2线程持有a锁,试图获取a锁");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a){
                    System.out.println("t2线程获取到a锁");
                }
            }
        },"t2").start();
    }
}

如何排查死锁

命令行

jsp -l
jstack pid
leam@Leam-MacBook-Pro locks % jps -l
3266 com.intellij.idea.Main
1609 /Users/xxx/.vscode/extensions/redhat.java-1.26.0-darwin-arm64/server/plugins/org.eclipse.equinox.launcher_1.6.700.v20231214-2017.jar
6301 org.jetbrains.jps.cmdline.Launcher
6302 dev.matrixlab.juc.locks.DeadLockDemo
6318 jdk.jcmd/sun.tools.jps.Jps
leam@Leam-MacBook-Pro locks % jstack 6302
2024-01-24 23:20:20
Full thread dump OpenJDK 64-Bit Server VM (25.382-b05 mixed mode):

"Attach Listener" #14 daemon prio=9 os_prio=31 tid=0x0000000150026000 nid=0x4707 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #13 prio=5 os_prio=31 tid=0x000000014e034000 nid=0x1103 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"t2" #12 prio=5 os_prio=31 tid=0x000000014d020000 nid=0x5b03 waiting for monitor entry [0x000000017861e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at dev.matrixlab.juc.locks.DeadLockDemo.lambda$main$1(DeadLockDemo.java:33)
        - waiting to lock <0x0000000715778fa0> (a java.lang.Object)
        - locked <0x0000000715778fb0> (a java.lang.Object)
        at dev.matrixlab.juc.locks.DeadLockDemo$$Lambda$2/396873410.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:750)

"t1" #11 prio=5 os_prio=31 tid=0x000000014d01d000 nid=0x5a03 waiting for monitor entry [0x0000000178412000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at dev.matrixlab.juc.locks.DeadLockDemo.lambda$main$0(DeadLockDemo.java:19)
        - waiting to lock <0x0000000715778fb0> (a java.lang.Object)
        - locked <0x0000000715778fa0> (a java.lang.Object)
        at dev.matrixlab.juc.locks.DeadLockDemo$$Lambda$1/1721931908.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:750)

"Service Thread" #10 daemon prio=9 os_prio=31 tid=0x000000013d02c000 nid=0x5803 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x000000014d81b000 nid=0x7f03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #8 daemon prio=9 os_prio=31 tid=0x000000014d81a800 nid=0x5503 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=31 tid=0x000000014e022000 nid=0x4f03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=31 tid=0x000000014e021000 nid=0x4e03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x000000014f8f2800 nid=0x5203 runnable [0x000000016f47e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x0000000715871138> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x0000000715871138> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:53)

"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x000000014f864800 nid=0x4b03 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x000000015000a800 nid=0x3403 in Object.wait() [0x000000016ef4e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000715588f08> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x0000000715588f08> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:188)

"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x000000014f850000 nid=0x3503 in Object.wait() [0x000000016ed42000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000715586ba0> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x0000000715586ba0> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=31 tid=0x000000014f84b000 nid=0x3203 runnable 

"ParGC Thread#0" os_prio=31 tid=0x000000014d80a800 nid=0x2203 runnable 

"ParGC Thread#1" os_prio=31 tid=0x000000014d816800 nid=0x3f03 runnable 

"ParGC Thread#2" os_prio=31 tid=0x000000014d817800 nid=0x3d03 runnable 

"ParGC Thread#3" os_prio=31 tid=0x000000013d00f000 nid=0x3b03 runnable 

"ParGC Thread#4" os_prio=31 tid=0x000000013d00f800 nid=0x2b03 runnable 

"ParGC Thread#5" os_prio=31 tid=0x000000014d818000 nid=0x2d03 runnable 

"ParGC Thread#6" os_prio=31 tid=0x000000014d819000 nid=0x3803 runnable 

"ParGC Thread#7" os_prio=31 tid=0x000000014d819800 nid=0x2f03 runnable 

"ParGC Thread#8" os_prio=31 tid=0x000000014e009800 nid=0x3003 runnable 

"VM Periodic Task Thread" os_prio=31 tid=0x000000014f8f3800 nid=0x7e03 waiting on condition 

JNI global references: 320


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

Java stack information for the threads listed above:
===================================================
"t2":
        at dev.matrixlab.juc.locks.DeadLockDemo.lambda$main$1(DeadLockDemo.java:33)
        - waiting to lock <0x0000000715778fa0> (a java.lang.Object)
        - locked <0x0000000715778fb0> (a java.lang.Object)
        at dev.matrixlab.juc.locks.DeadLockDemo$$Lambda$2/396873410.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:750)
"t1":
        at dev.matrixlab.juc.locks.DeadLockDemo.lambda$main$0(DeadLockDemo.java:19)
        - waiting to lock <0x0000000715778fb0> (a java.lang.Object)
        - locked <0x0000000715778fa0> (a java.lang.Object)
        at dev.matrixlab.juc.locks.DeadLockDemo$$Lambda$1/1721931908.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:750)

Found 1 deadlock.

图形化界面

jconsole

jconsole 示例1

jconsole 示例2

jconsole 示例3