如何以编程方式生成 Java 死锁以及如何分析死锁
已发表: 2013-07-03死锁是两个或多个线程被永远阻塞的编程情况,这种情况出现在至少两个线程和两个或更多资源的情况下。
在这里,我编写了一个简单的程序,会导致死锁的情况,然后我们将看看如何分析它。
这是一个简单的 Java 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
package com . crunchify . tutorials ; import java . lang . management . ManagementFactory ; import java . lang . management . ThreadInfo ; import java . lang . management . ThreadMXBean ; /** * @author Crunchify.com * */ public class CrunchifyThreadDeadLock { public static void main ( String [ ] args ) throws InterruptedException { Object obj1 = new Object ( ) ; Object obj2 = new Object ( ) ; Object obj3 = new Object ( ) ; Thread crunchifyThread1 = new Thread ( new CrunchifySynchronizeThread ( obj1 , obj2 ) , "crunchifyThread1" ) ; Thread crunchifyThread2 = new Thread ( new CrunchifySynchronizeThread ( obj2 , obj3 ) , "crunchifyThread2" ) ; Thread crunchifyThread3 = new Thread ( new CrunchifySynchronizeThread ( obj3 , obj1 ) , "crunchifyThread3" ) ; crunchifyThread1 . start ( ) ; Thread . sleep ( 3000 ) ; crunchifyThread2 . start ( ) ; Thread . sleep ( 3000 ) ; crunchifyThread3 . start ( ) ; } } class CrunchifySynchronizeThread implements Runnable { private Object obj1 ; private Object obj2 ; public CrunchifySynchronizeThread ( Object obj1 , Object obj2 ) { this . obj1 = obj1 ; this . obj2 = obj2 ; } @Override public void run ( ) { String name = Thread . currentThread ( ) . getName ( ) ; synchronized ( obj1 ) { System . out . println ( name + " acquired lock on Object1: " + obj1 ) ; try { Thread . sleep ( 10000 ) ; } catch ( InterruptedException e ) { e . printStackTrace ( ) ; } synchronized ( obj2 ) { System . out . println ( name + " acquired lock on Object2: " + obj2 ) ; } System . out . println ( name + " released lock on Object2: " + obj2 ) ; } System . out . println ( name + " released lock on Object1: " + obj1 ) ; System . out . println ( name + " Finished Crunchify Deadlock Test." ) ; } } |
输出:

1 2 3 |
crunchifyThread1 acquired lock on Object1 : java . lang . Object @ 59e3bddb crunchifyThread2 acquired lock on Object1 : java . lang . Object @ 294e430c crunchifyThread3 acquired lock on Object1 : java . lang . Object @ 246972f1 |
当您的应用程序像上面的示例一样挂起时,您可以获得线程转储并查看死锁线程。
例如,在 Mac 上,您可以执行Ctrl-\
或简单地使用jstack
和进程 ID 来获取线程转储,这使得死锁的位置非常明显。
在此示例中,线程转储如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
"crunchifyThread3" java . lang . Thread . State : RUNNABLE at sun . management . ThreadImpl . getThreadInfo1 ( Native Method ) at sun . management . ThreadImpl . getThreadInfo ( ThreadImpl . java : 174 ) at com . crunchify . tutorials . CrunchifySynchronizeThread . getThreadDump ( CrunchifyThreadDeadLock . java : 64 ) at com . crunchify . tutorials . CrunchifySynchronizeThread . run ( CrunchifyThreadDeadLock . java : 50 ) at java . lang . Thread . run ( Thread . java : 722 ) "crunchifyThread2" java . lang . Thread . State : BLOCKED at com . crunchify . tutorials . CrunchifySynchronizeThread . run ( CrunchifyThreadDeadLock . java : 53 ) at java . lang . Thread . run ( Thread . java : 722 ) "crunchifyThread1" java . lang . Thread . State : BLOCKED at com . crunchify . tutorials . CrunchifySynchronizeThread . run ( CrunchifyThreadDeadLock . java : 53 ) at java . lang . Thread . run ( Thread . java : 722 ) "Signal Dispatcher" java . lang . Thread . State : RUNNABLE "Finalizer" java . lang . Thread . State : WAITING at java . lang . Object . wait ( Native Method ) at java . lang . ref . ReferenceQueue . remove ( ReferenceQueue . java : 135 ) at java . lang . ref . ReferenceQueue . remove ( ReferenceQueue . java : 151 ) at java . lang . ref . Finalizer $ FinalizerThread . run ( Finalizer . java : 189 ) "Reference Handler" java . lang . Thread . State : WAITING at java . lang . Object . wait ( Native Method ) at java . lang . Object . wait ( Object . java : 503 ) at java . lang . ref . Reference $ ReferenceHandler . run ( Reference . java : 133 ) |
注意这里 BLOCKED 和 WAITING threads => Deadlock
情况。在下一个示例中,将提供简单的 Java 程序以编程方式生成上述线程转储。