死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
死锁的发生是由于资源竞争导致的,导致死锁的原因如下:
死锁的发生的四个必要条件:
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
1.1:编写死锁代码
Lock lock1 = new ReentrantLock(); Lock lock2 = new ReentrantLock(); ExecutorService exectuorService = Executors.newFixedThreadPool(2); exectuorService.submit(() -> { lock1.lock(); try{ Thread.sleep(1000); }catch(Exception e){} try{} finally{ lock1.unlock(); lock2.unlock(); } }); exectuorService.submit(() -> { lock2.lock(); try{ Thread.sleep(1000); }catch(Exception e){} try{} finally{ lock1.unlock(); lock2.unlock(); } });
"DestroyJavaVM" #13 prio=5 os_prio=31 tid=0x00007f9a1d8fe800 nid=0xd03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "pool-1-thread-2" #12 prio=5 os_prio=31 tid=0x00007f9a1d8fe000 nid=0xa703 waiting on condition [0x000070000ff8e000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x0000000795768cd8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at com.coco.util.SlideTimeUnit.lambda$main$1(SlideTimeUnit.java:63) at com.coco.util.SlideTimeUnit$$Lambda$2/565760380.run(Unknown Source) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) 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: - <0x0000000795768d08> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) - <0x0000000795a9e4e0> (a java.util.concurrent.ThreadPoolExecutor$Worker) "pool-1-thread-1" #11 prio=5 os_prio=31 tid=0x00007f9a2082c800 nid=0xa803 waiting on condition [0x000070000fe8b000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x0000000795768d08> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at com.coco.util.SlideTimeUnit.lambda$main$0(SlideTimeUnit.java:49) at com.coco.util.SlideTimeUnit$$Lambda$1/596512129.run(Unknown Source) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) 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: - <0x0000000795768cd8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) - <0x0000000795a9ba28> (a java.util.concurrent.ThreadPoolExecutor$Worker) "Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007f9a2082c000 nid=0x4103 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x00007f9a1e021800 nid=0x3f03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
2.1: 下载好Arthas的jar,然后运行
有一个 thread -b 就可以查看到死锁信息
[arthas@4182]$ thread -b "pool-1-thread-2" Id=12 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@2cb8a9a3 owned by "pool-1-thread-1" Id=11 at sun.misc.Unsafe.park(Native Method) - waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@2cb8a9a3 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at com.coco.util.SlideTimeUnit.lambda$main$1(SlideTimeUnit.java:63) at com.coco.util.SlideTimeUnit$$Lambda$2/565760380.run(Unknown Source) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) 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) Number of locked synchronizers = 2 - java.util.concurrent.ThreadPoolExecutor$Worker@6433a2 - java.util.concurrent.locks.ReentrantLock$NonfairSync@3a855d13 <---- but blocks 1 other threads!
Jvisualvm 是一种自带的可视化工具,往往在在本地执行。
通过 Jvisualvm 命令打开软件,选中进程,进入线程视图,会给出死锁提示: