Como gerar Java Deadlock programaticamente e como analisar Deadlock
Publicados: 2013-07-03Deadlock é uma situação de programação onde dois ou mais threads são bloqueados para sempre, esta situação surge com pelo menos dois threads e dois ou mais recursos.
Aqui eu escrevi um programa simples que causará um cenário de deadlock e então veremos como analisá-lo.
Aqui está um exemplo simples de 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." ) ; } } |
Saída:

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 |
Enquanto seu aplicativo está travando como no exemplo acima, você pode obter um despejo de thread e ver os threads bloqueados.
Por exemplo, no Mac, você pode fazer Ctrl-\
ou simplesmente usar jstack
e process id para obter o despejo de encadeamento, o que torna muito óbvio onde está o impasse.
Neste exemplo, o dump de encadeamento se parece com isso:
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 ) |
Notificado aqui BLOCKED and WAITING threads => Deadlock
aqui .. No próximo exemplo, fornecerá um programa Java simples para gerar o dump de thread acima programaticamente.