프로그래밍 방식으로 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 프로그램을 제공합니다.