동기화에의한 Thread Deadlock 엑셈컨설팅본부 /APM 지원팀한승민 개요 Java 객체나 method 의동시성제어를위한동기화기법을잘못사용하였을때나타나는 Thread 간의 Deadlock 으로인한 Transaction 지연상황에대하여살펴보도록하자. 멀티쓰레드환경에서공유객체의연산을수행하는블럭에 synchronized 를사용하는경우해당객체의 read, write 작업은모두직렬화되어맨처음동기화된블럭에접근한 Thread 의작업이끝나기전까지다른 thread 는동일객체에대해쓰기는물론읽기작업조차도수행할수없는상태가된다. 이러한제약자체만으로도성능에영향을미치는것은구태여설명하지않아도될것이다. 동기화기법을사용할때발생하게되는성능이슈중가장큰문제가바로 Thread 간 Deadlock 현상이다. 공유객체인 A 객체와 B 객체가존재한다고가정할때 A, B 객체를상호교차참조하는연산을수행하는동기화된블록을가진두개의어플리케이션이존재할때 Deadlock 이발생하게되는데이문제를방지하기위해서는동기화블록내의연산수행범위를최소화하고, A,B 객체의참조순서가같게하거나 A,B 객체를참조하는별도의객체를생성하여사용하는방향으로로직의수정이필요하다. 이밖에도 Java5.0 부터새로지원하는동기화기법인 Lock Interface 를사용하여 Deadlock 상황을최소화하고성능개선을꾀할수도있다. 그러나이 Lock Interface 의사용도 Deadlock 의발생을원천적으로막아줄수는없다. Deadlock 은동기화기법을잘못활용하였을때발생한다는점에서로직설계및개발시점에소스수정단계에서공유객체에대한동기화를사용하는어플리케이션에대한확실한검증을거치지않은것이원인이되는경우가대부분이기때문이다. 역시이문제의해결은개발단계에서부터상호교차참조를하지않도록로직을구현하는방법이유일하다할것이다. 기본적으로 JAVA 에서 Thread 는서로다른 Thread 의작업에대하여영향을주지않고독립적 으로수행이가능하도록구현되어있다. Part 2 APM 405
<Thread 와 A 객체의메소드간의접근관계 > 그림과같이각각의 Thread 는 A 객체의모든 public Method 에대해중복접근이허용된다. 이는 WAS 의목적인 Web Service 환경에서다수의요청을효율적으로처리하기위한목적에서비롯된것이다. 즉직렬처리에서오는한계점을극복하기위해모든 Thread 가각각의요청을별도로수행할수있도록병렬처리가가능하게구현되어있기때문이다. 그러나이러한 WAS 환경에서도직렬처리가필요한상황이분명존재하기마련이다. 단순히저장되어있는 Data 를보여주기위한연산이아니라 Data 수정해야하는상황이온다면, 거기에더불어해당 Data 는 WAS 에접근하는모든요청에대해유일성을지니는공유 Data 라면문제가달라지게된다. 즉동기화기법이적용되어야하는것이다. 이러한패턴을 Single Threaded Execution 이라하는데이패턴을구현하는데가장대표적으로이용되는것이 Synchronized 기법이다. Synchronized 로선언된객체나 Method, 또는 Method 내의블록에 Thread 가접근하기위해서는 monitor 라고불리는 Lock 을획득해야한다. 이러한 Lock 을통해서해당 Data 에대해유일성을보장하고직렬처리를가능하게하는것이다. 406 2013 기술백서 White Paper
<Synchronized 기법을사용한경우 > B Method 가 Synchronized 로지정된경우이전과는다르게 1 번 Thread 가 B Method 의수행을종료할때까지 2 번 Thread 는대기하게된다. 이는 B Method 에 monitor Lock 이구현되었기때문으로만약 B Method 가매우빈번하게수행되고수행시간이오래걸리는 Method 라면 Transaction 수행성능에매우좋지않은영향을줄수있다. 그래서일반적으로 Synchronized 로선언하는경우해당객체나 Method, 블록의수행범위를최소화할것을권장하고있다. Synchronized 기법에서발생할수있는또한가지의문제점이바로 Deadlock 이다. Deadlock 은상호배타적인접근을동시수행하려할때발생하는현상인데예를들어 Thread 1 번이 Transaction 수행중 A 객체에대한 monitor Lock 을잡은상태에서 B 객체에대해 monitor Lock 을잡기위해접근하는상황에서 Thread 2 번이 B 객체에대해 monitor Lock 을획득하고연산을수행하는도중에 A 객체의 monitor Lock 을잡기위해대기하는상황이발생한다. 이렇게서로가서로의 Lock 을먼저해제하기만을기다리고있는상황이바로 Deadlock 현상이다. Part 2 APM 407
<Thread Deadlock 상황 > Thread 가 Deadlock 상황에빠지게되면서로다른쪽의 monitor Lock 을획득하기위해무한히대기하게된다. 이러한 Transaction 이빈번하게수행된다면얼마지나지않아가용 Thread 가전부소진되어서비스장애상황에놓이게될것이다. Synchronized 를사용해야만하는환경에서 Deadlock 을회피하기위한방법은어찌보면굉장히단순하고쉽다. Synchronized 로동기화된자원에대해어떤 Application 이든지항상같은순서로참조하게하면되는것이다. 위의상황에서 B, C Method 를수행하는모든 Application 이 B Method 수행후에 C Method 를수행하도록짜여져있다면 Deadlock 은절대발생하지않을것이다. 이는대부분의 Deadlock 이로직의설계과정이나실제구현단계에서의착오로발생하는것이기때문에미연에방지가가능함을말하는것이다. 그리고만약발생하였다하더라도아래의방법을통해어떠한 Application 에의해발생되었는지파악이가능하다면어렵지않게조치가가능할것이다. JVM Thread Dump Thread Dump 는특정시간에 JVM 상에서수행중인 Thread 의상태정보에대한일종의 snapshot 으로 Transaction 이지연되는시점에 Thread Dump 를받으면그당시각 Thread 가어떤일을수행하고어떠한상태에있는지파악할수있도록많은정보를제공하고있다. 408 2013 기술백서 White Paper
Thread Dump 를받기위해서는 UNIX/Linux : kill -3 <JVM PID> Windows : Ctrl+Break 명령을이용한다. Dump 결과는 Console 에출력되므로 Redirection 을통해서파일로저장하 여사용하도록한다. 1 "http1-w19 [container1-26]" prio=1 tid=0x08e718b0 nid=0x19c9 waiting for monitor entry 3 [0xd4b79000..0xd4b7a198] 2 at sfairpkg.dlock.run3(dlock.java:47) - waiting to lock <0xeffc9ce8> (a java.lang.class) at jeus_jspwork._500_sfairap_5fdeadlock3_5fjsp._jspservice(_500_sfairap_5fdeadlock3_5fjsp.java:54) at jeus.servlet.jsp.httpjspbase.service(httpjspbase.java:53) <Thread Dump -SUN JVM 1.4> 4 위의내용은 Thread Dump 중한 Thread 의정보만을추려낸것이다. 각항목에대해살펴보면 1. Thread Name : Thread 의이름을나타냄. (WAS 벤더에따라보여주는형식이약간씩 다름.) 2. Thread id : system 에서부여된 Thread ID 3. Thread status : Thread 의수행상태정보 (JVM 별로다름 ) 4. Stack Trace : 당시의 Thread 에서수행중인 Class Method 수행정보 크게네영역으로나뉘어지는데각영역이담고있는내용은 WAS 벤더와 JVM 종류별로약간 씩의차이가있으므로기본적인의미만이해할수있으면된다. 위의 Thread Dump 내용을대략적으로해석하면 Dump 수행당시 http1-w19 라는이름을가 진 Thread ID 0x08e718b0 의 Thread 가 monitor entry 에접근하기위해 waiting 을하고 Part 2 APM 409
있으며수행중인 Class Method 는 sfairpkg.dlock.run3 이고 0xeffc9ce8 객체의 monitor lock 을획득하려하는중이었음을알수있다. 이처럼 Thread Dump 를이용하면당시 WAS 의모든 Thread 에대한상태정보를얻을수있어 Transaction 지연의원인을찾는데중요한단서를제공받을수있으므로 Transaction 처리가늦어지는시점에 1~2 초간격으로두세번정도의 Dump 를받아놓으면사후분석에유용하게활용할수있다. 이러한 Thread Dump 는기본적으로텍스트형식으로받을수있는데분석하기에쉽지않게되어있기때문에 GUI 를통해보다쉽게분석이가능하도록하는공개프로그램들을사용하는것이좋다. 이툴들가운데쓰기에간편한 Thread Dump 분석전용프로그램인 SAMURAI 의사용법에대하여간략하게설명하도록하겠다. SAMURAI 는 Yusuke Yamamoto 라는일본인이제작한 Dump 분석도구로 Thread Dump, GC Dump 등을손쉽게분석할수있도록도와주는프로그램이다. SAMURAI 의홈페이지에가서프로그램을직접수행해볼수도있고 PC 로다운받아 java jre samurai.jar 명령을통해수행할수도있다. 1 <SAMURAI 실행화면 > 1 이툴은 http://yusuke.homeip.net/samurai/en/index.html#threaddumpanalysis 에서 다운로드및사용이가능하다. 410 2013 기술백서 White Paper
프로그램을실행하면빈화면이나타나는데사용법도매우간단하다. 받아놓은 Thread Dump 텍스트파일을드래그해서올려놓거나 File>Open 메뉴에서불러오기만하면된다. <Thread Dump 분석후화면 > Thread Dump 파일을읽어들인후두개의 Tab 이생기는데그중 Log Tab 은 Dump 의내용 을볼수있는메뉴이고 Thread Dumps 는 Dump 의내용을분석하여 Thread 의상태를테이 블의형태로보여주는메뉴이다. Part 2 APM 411
<Thread 상태표시화면 > 화면의좌측은 Thread List 를보여주고우측은각 Thread 의 Dump 당시상태를색상을통해 나타내고있다. Deadlock 은해골그림으로표시되어알기쉽게표현하고있다. <Deadlock 상태인 Thread 정보 > 412 2013 기술백서 White Paper
결론 이처럼문제시점의 Thread Dump 는 Transaction 지연원인분석에많은단서를제공해주기때문에장애발생시나 Transaction 지연시에는 Dump 를받아놓는것이관리측면에서매우유용할것이다. 이번에소개한 SAMURAI 프로그램은간단하면서도분석에필요한 Thread 상태정보를알기쉽게표현해주고있다. 이밖에도각 OS JVM 벤더별로자체제공하는유용한분석프로그램들이많이있는데이를십분활용한다면대부분의성능지연의원인을어렵지않게분석해낼수있을것이다. Part 2 APM 413