就是,两个线程互相等待着对象释放锁,一直这样僵持下去,所以导致了死锁的产生,下面这个代码就会产生一个死锁:
package com.example.demo.thread;
public class DeadLockDemo {
private static String A = "A";
private static String B = "B";
public static void main(String[] args) {
new DeadLockDemo().deadLock();
}
private void deadLock() {
Thread t1 = new Thread(() -> {
synchronized (A){
try {
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
synchronized (B){
System.out.println("1");
}
}
});
Thread t2 = new Thread(()->{
synchronized (B){
synchronized (A){
System.out.println("2");
}
}
});
t1.start();
t2.start();
}
}
代码来源于《Java并发编程艺术之美》,当我运行了该程序后,一直没有输出,采用visualVM工具来进行诊断,结果如下图所示:
从该图中,我们可以看出,DeadLockDemo
类的线程的pid=6428
,,可以看到红色框中提示,有死锁存在。
然后点击右上角的Thread Dump
文件,来分析一下该文件的内容,具体内容如下:
2019-06-28 21:11:20
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode):
"RMI TCP Connection(2)-10.2.4.117" #19 daemon prio=5 os_prio=0 tid=0x000000001c6c2800 nid=0x442c runnable [0x000000001dc6d000]
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 java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x0000000781963ed0> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5/904339139.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- <0x0000000781599378> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"JMX server connection timeout 18" #18 daemon prio=5 os_prio=0 tid=0x000000001c639800 nid=0x1f64 in Object.wait() [0x000000001db6f000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000781703b78> (a [I)
at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
- locked <0x0000000781703b78> (a [I)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"RMI Scheduler(0)" #17 daemon prio=5 os_prio=0 tid=0x000000001c638800 nid=0x305c waiting on condition [0x000000001da6f000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007814abc08> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"RMI TCP Connection(1)-10.2.4.117" #16 daemon prio=5 os_prio=0 tid=0x000000001bd25800 nid=0x389c runnable [0x000000001d96d000]
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 java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x00000007816892c0> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5/904339139.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- <0x0000000781594850> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"RMI TCP Accept-0" #15 daemon prio=5 os_prio=0 tid=0x000000001bcdc000 nid=0x2674 runnable [0x000000001d76e000]
java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
- locked <0x00000007814bd318> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:405)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000003454000 nid=0x2f28 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001c654800 nid=0x42e8 waiting for monitor entry [0x000000001cf4f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.demo.thread.DeadLockDemo.lambda$deadLock$1(DeadLockDemo.java:27)
- waiting to lock <0x0000000780ae7e30> (a java.lang.String)
- locked <0x0000000780ae7e60> (a java.lang.String)
at com.example.demo.thread.DeadLockDemo$$Lambda$2/2128227771.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Thread-0" #11 prio=5 os_prio=0 tid=0x000000001c652000 nid=0x22d4 waiting for monitor entry [0x000000001ce4e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.demo.thread.DeadLockDemo.lambda$deadLock$0(DeadLockDemo.java:20)
- waiting to lock <0x0000000780ae7e60> (a java.lang.String)
- locked <0x0000000780ae7e30> (a java.lang.String)
at com.example.demo.thread.DeadLockDemo$$Lambda$1/2121055098.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x000000001bbd3800 nid=0x3654 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001bb51000 nid=0x3020 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001bb45800 nid=0x4050 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001bb44800 nid=0x4634 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001bb26800 nid=0x43b8 runnable [0x000000001c02e000]
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 <0x0000000780b2bb38> (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 <0x0000000780b2bb38> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
Locked ownable synchronizers:
- None
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001b93b800 nid=0x5dc waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001a63e800 nid=0x4770 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000000354e000 nid=0x3fdc in Object.wait() [0x000000001b92f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000780908ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x0000000780908ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001a5ca800 nid=0x1b38 in Object.wait() [0x000000001b82f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000780906bf8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x0000000780906bf8> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=2 tid=0x000000001a5a7000 nid=0x3b50 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x000000000346a800 nid=0x4698 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000000000346c000 nid=0x4048 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000346d800 nid=0x3f94 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000346f000 nid=0x39b4 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x000000001bc25000 nid=0x1950 waiting on condition
JNI global references: 338
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x000000000354c3b8 (object 0x0000000780ae7e30, a java.lang.String),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000000354d7a8 (object 0x0000000780ae7e60, a java.lang.String),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.example.demo.thread.DeadLockDemo.lambda$deadLock$1(DeadLockDemo.java:27)
- waiting to lock <0x0000000780ae7e30> (a java.lang.String)
- locked <0x0000000780ae7e60> (a java.lang.String)
at com.example.demo.thread.DeadLockDemo$$Lambda$2/2128227771.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at com.example.demo.thread.DeadLockDemo.lambda$deadLock$0(DeadLockDemo.java:20)
- waiting to lock <0x0000000780ae7e60> (a java.lang.String)
- locked <0x0000000780ae7e30> (a java.lang.String)
at com.example.demo.thread.DeadLockDemo$$Lambda$1/2121055098.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
通过上面的线程Dump文件信息,我们可以看出来发生了死锁,下面也列出了java级别的锁问题和栈信息:
并且栈信息中,可以定位到死锁发生的地方。
如果解决死锁,那是因为代码的逻辑存在问题,可以调整代码的逻辑或者业务,来避免死锁。