Comment générer un blocage Java par programme et comment analyser un blocage
Publié: 2013-07-03Le blocage est une situation de programmation où deux ou plusieurs threads sont bloqués pour toujours, cette situation se produit avec au moins deux threads et deux ressources ou plus.
Ici, j'ai écrit un programme simple qui provoquera un scénario de blocage et nous verrons ensuite comment l'analyser.
Voici un exemple Java simple :
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." ) ; } } |
Sortir:

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 |
Pendant que votre application est suspendue comme dans l'exemple ci-dessus, vous pouvez obtenir un vidage de thread et voir les threads bloqués.
Par exemple, sur Mac, vous pouvez soit faire Ctrl-\
ou simplement utiliser jstack
et process id pour obtenir le vidage du thread, ce qui rend très évident l'endroit où se trouve le blocage.
Dans cet exemple, le thread dump ressemble à ceci :
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 ) |
Remarqué ici Threads BLOQUÉS et EN ATTENTE threads => Deadlock
ici .. Dans l'exemple suivant, nous fournirons un programme Java simple pour générer le vidage de thread ci-dessus par programme.