原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11424647.html
死锁:一组互相竞争资源的线程因互相等待,导致“永久”阻塞的现象。
解决死锁,要么重启,要么规避
那如何避免死锁呢?要避免死锁就需要分析死锁发生的条件,只有以下这四个条件都发生时才会出现死锁:
- 互斥,共享资源 X 和 Y 只能被一个线程占用;
- 占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;
- 不可抢占,其他线程不能强行抢占线程 T1 占有的资源;
- 循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。
反过来分析,也就是说只要破坏其中一个,就可以成功避免死锁的发生。
模拟一个死锁的程序
1 package org.fool.test; 2 3 import java.util.concurrent.TimeUnit; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class DeadLockTest { 8 private static Lock lockA = new ReentrantLock(); 9 private static Lock lockB = new ReentrantLock(); 10 11 public static void main(String[] args) { 12 new Thread(new Runnable() { 13 @Override 14 public void run() { 15 try { 16 lockA.lock(); 17 System.out.println("=====Thread A outer invoked...====="); 18 TimeUnit.SECONDS.sleep(3); 19 try { 20 lockB.lock(); 21 System.out.println("=====Thread A inner invoked...====="); 22 } finally { 23 lockB.unlock(); 24 } 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } finally { 28 lockA.unlock(); 29 } 30 } 31 }, "Thread-A").start(); 32 33 new Thread(new Runnable() { 34 @Override 35 public void run() { 36 try { 37 lockB.lock(); 38 System.out.println("=====Thread B outer invoked...====="); 39 TimeUnit.SECONDS.sleep(3); 40 try { 41 lockA.lock(); 42 System.out.println("=====Thread B inner invoked...====="); 43 } finally { 44 lockA.unlock(); 45 } 46 } catch (InterruptedException e) { 47 e.printStackTrace(); 48 } finally { 49 lockB.unlock(); 50 } 51 } 52 }, "Thread-B").start(); 53 } 54 55 }
打包成可执行jar包后,运行java -jar hello-deadlock-1.0-SNAPSHOT.jar
ps -ef | grep java 找出对应的pid,使用jstack打出堆栈信息
1 2019-04-25 15:49:30 2 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode): 3 4 "Attach Listener" #13 daemon prio=9 os_prio=31 tid=0x00007fb881058800 nid=0x1407 waiting on condition [0x0000000000000000] 5 java.lang.Thread.State: RUNNABLE 6 7 "DestroyJavaVM" #12 prio=5 os_prio=31 tid=0x00007fb882802000 nid=0x1c03 waiting on condition [0x0000000000000000] 8 java.lang.Thread.State: RUNNABLE 9 10 "Thread-B" #11 prio=5 os_prio=31 tid=0x00007fb883807000 nid=0x5903 waiting on condition [0x0000700002f89000] 11 java.lang.Thread.State: WAITING (parking) 12 at sun.misc.Unsafe.park(Native Method) 13 - parking to wait for <0x000000076abdaa00> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) 14 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 15 at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) 16 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) 17 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) 18 at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) 19 at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) 20 at org.fool.test.DeadLockTest$2.run(DeadLockTest.java:41) 21 at java.lang.Thread.run(Thread.java:745) 22 23 "Thread-A" #10 prio=5 os_prio=31 tid=0x00007fb8800a7800 nid=0x5703 waiting on condition [0x0000700002e86000] 24 java.lang.Thread.State: WAITING (parking) 25 at sun.misc.Unsafe.park(Native Method) 26 - parking to wait for <0x000000076abdaa30> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) 27 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 28 at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) 29 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) 30 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) 31 at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) 32 at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) 33 at org.fool.test.DeadLockTest$1.run(DeadLockTest.java:20) 34 at java.lang.Thread.run(Thread.java:745) 35 36 "Service Thread" #9 daemon prio=9 os_prio=31 tid=0x00007fb882051000 nid=0x5303 runnable [0x0000000000000000] 37 java.lang.Thread.State: RUNNABLE 38 39 "C1 CompilerThread3" #8 daemon prio=9 os_prio=31 tid=0x00007fb880009800 nid=0x5103 waiting on condition [0x0000000000000000] 40 java.lang.Thread.State: RUNNABLE 41 42 "C2 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007fb881044000 nid=0x4f03 waiting on condition [0x0000000000000000] 43 java.lang.Thread.State: RUNNABLE 44 45 "C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007fb881043000 nid=0x4d03 waiting on condition [0x0000000000000000] 46 java.lang.Thread.State: RUNNABLE 47 48 "C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007fb882025800 nid=0x4b03 waiting on condition [0x0000000000000000] 49 java.lang.Thread.State: RUNNABLE 50 51 "Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fb88200c800 nid=0x4903 runnable [0x0000000000000000] 52 java.lang.Thread.State: RUNNABLE 53 54 "Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fb880858000 nid=0x3903 in Object.wait() [0x000070000266e000] 55 java.lang.Thread.State: WAITING (on object monitor) 56 at java.lang.Object.wait(Native Method) 57 - waiting on <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock) 58 at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) 59 - locked <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock) 60 at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164) 61 at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209) 62 63 "Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fb880855800 nid=0x3703 in Object.wait() [0x000070000256b000] 64 java.lang.Thread.State: WAITING (on object monitor) 65 at java.lang.Object.wait(Native Method) 66 - waiting on <0x000000076ab06b68> (a java.lang.ref.Reference$Lock) 67 at java.lang.Object.wait(Object.java:502) 68 at java.lang.ref.Reference.tryHandlePending(Reference.java:191) 69 - locked <0x000000076ab06b68> (a java.lang.ref.Reference$Lock) 70 at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) 71 72 "VM Thread" os_prio=31 tid=0x00007fb881002800 nid=0x3503 runnable 73 74 "GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fb880014800 nid=0x2503 runnable 75 76 "GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fb880015800 nid=0x2703 runnable 77 78 "GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007fb880016000 nid=0x2903 runnable 79 80 "GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007fb880016800 nid=0x2b03 runnable 81 82 "GC task thread#4 (ParallelGC)" os_prio=31 tid=0x00007fb881001000 nid=0x2d03 runnable 83 84 "GC task thread#5 (ParallelGC)" os_prio=31 tid=0x00007fb881002000 nid=0x2f03 runnable 85 86 "GC task thread#6 (ParallelGC)" os_prio=31 tid=0x00007fb880800800 nid=0x3103 runnable 87 88 "GC task thread#7 (ParallelGC)" os_prio=31 tid=0x00007fb880801000 nid=0x3303 runnable 89 90 "VM Periodic Task Thread" os_prio=31 tid=0x00007fb880828800 nid=0x5503 waiting on condition 91 92 JNI global references: 6 93 94 95 Found one Java-level deadlock: 96 ============================= 97 "Thread-B": 98 waiting for ownable synchronizer 0x000000076abdaa00, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), 99 which is held by "Thread-A" 100 "Thread-A": 101 waiting for ownable synchronizer 0x000000076abdaa30, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), 102 which is held by "Thread-B" 103 104 Java stack information for the threads listed above: 105 =================================================== 106 "Thread-B": 107 at sun.misc.Unsafe.park(Native Method) 108 - parking to wait for <0x000000076abdaa00> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) 109 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 110 at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) 111 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) 112 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) 113 at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) 114 at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) 115 at org.fool.test.DeadLockTest$2.run(DeadLockTest.java:41) 116 at java.lang.Thread.run(Thread.java:745) 117 "Thread-A": 118 at sun.misc.Unsafe.park(Native Method) 119 - parking to wait for <0x000000076abdaa30> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) 120 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 121 at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) 122 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) 123 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) 124 at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) 125 at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) 126 at org.fool.test.DeadLockTest$1.run(DeadLockTest.java:20) 127 at java.lang.Thread.run(Thread.java:745) 128 129 Found 1 deadlock.
Note:
tid: java线程ID
nid: native线程ID