본문 바로가기

1. Thread란

 

쓰레드는 프로세스 내부에서 작업을 실행해주는 흐름이다. 한개의 프로세스에는 반드시 1개의 쓰레드가 존재하고 여러개의 쓰레드가 동작하기도한다.

 

2. Thread Dump란

여러개의 쓰레드를 실행을 하게되면 쓰레드끼리 공유하는 자원이 있다. 공유하는 자원에 여러개의 쓰레드가 동시에 접근해서 데이터를 변경하면 의도치않은 결과가 발생한다. 이를 방지하기 위해서 공유자원에 접근하는 쓰레드를 제한하는 방법을 제공해준다. 이렇게 잠금을 획득하는 과정에서 쓰레드끼리 서로 같은 잠금을 획득하는 과정에서 DeadLock이 발생할 수 있는데 쓰레드 덤프를 활용하면 각 쓰레드의 상태를 파악할 수 있다. 쓰레드 덤프는 실행중인 애플리케이션의 쓰레드 상태정보를 알려주는것이다.

 

3. Thread Dump 활용

 

Thread Dump를 통해서 실행중인 애플리케이션의 쓰레드 정보를 확인해보자. 아래와 같이 DeadLock을 유발하는 코드를 생성했다. /lock-left로 요청이 들어오고 5초이내애 /lock-right로 다른 요청이 들어오게되면 두개의 스레드가 서로가 가진 잠금을 획득하려고 하면서 DeadLock 상태에 빠진다. 

 

공유자원인 `Object left`, `Object right`에 대해서 `lock-left`에 요청이 들어오면 left에 잠금을 걸고 5초 대기후 right 잠금을 획득하려고 한다. 5초가 지나기전에 `lock-right`에 요청이 들어오게되면 right에 잠금을 획득하고 5초를 기다리고 left잠금을 획득하려고한다. 이 과정에서 서로가 가지고 있는 키를 서로가 획득하려고하면서 dead lock이 발생하는것이다. 이제 실제로 쓰레드 덤프를 통해서 `deadlock-test-1`,`deadlock-test-2`쓰레드들의 상태를 확인해보자.

    static final Object left = new Object();
    static final Object right = new Object();
    
    @GetMapping("/lock-left")
    public String findLockLeft() throws InterruptedException {

        synchronized (left) {
            Thread.currentThread().setName("deadlock-test-1");
            Thread.sleep(5000);
            synchronized (right) {
                System.out.println("left");
            }
        }
        return "ok";
    }

    @GetMapping("/lock-right")
    public String findLockRight() throws InterruptedException {
        synchronized (right) {
            Thread.currentThread().setName("deadlock-test-2");
            Thread.sleep(5000);
            synchronized (left) {
                System.out.println("right");
            }
        }
        return "ok";
    }

 

쓰레드 덤프를 확인하기 위해서는 PID를 알아야한다  PID가  74947 것을 확인할 수 있다.

 

ps -ef | grep java
110536907 74947 33713   0  8:38PM ttys000   18:23.83 /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 @/var/folders/nx/4f2tsvbn0lv97hphhrpqk2ym39d_6b/T/cp_5dhe247w2xeddv80285ixbgns.argfile nextstep.subway.SubwayApplication

 

jstack 명령어로 thread dump파일을 생성시키고 어떤 내용이 들어있는지 확인해보자.

jstack 74947 > thread.dump

 

아래는 DeadLock을 발생시키고 thread dump를 만들어서 스레드의 정보가 출력되는 로그이다. `deadlock-test-1`이라는 쓰레드는 `0x0000000711527f38`잠금을 가지고 있고 `0x0000000711527f48`잠금을 획득하기 위해서 대기하고 있다. 반면, `deadlock-test-2`는 `0x0000000711527f48`잠금을 가지고 있고 `0x0000000711527f38`을 획득하기 위해서 대기하고 있다. 즉 서로가 가진 잠금을 획득하기 위해서 무한대기상태에 빠지는것이다.

 

 

"deadlock-test-1" #32 daemon prio=5 os_prio=31 cpu=2.35ms elapsed=508.24s tid=0x00007faae87dd800 nid=0x7603 waiting for monitor entry  [0x0000700005224000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at nextstep.subway.line.ui.LineController.findLockLeft(LineController.java:79)
	- waiting to lock <0x0000000711527f48> (a java.lang.Object)
	- locked <0x0000000711527f38> (a java.lang.Object)
    
    
    
 "deadlock-test-2" #33 daemon prio=5 os_prio=31 cpu=1.28ms elapsed=508.24s tid=0x00007faae87d1000 nid=0x7803 waiting for monitor entry  [0x0000700005327000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at nextstep.subway.line.ui.LineController.findLockRight(LineController.java:91)
	- waiting to lock <0x0000000711527f38> (a java.lang.Object)
	- locked <0x0000000711527f48> (a java.lang.Object)   

 

 

만들어진 dump파일을 https://fastthread.io/ft-index.jsp 에 업로드하면 훨씬 보기 좋게 분석해준다. 실행중인 쓰레드의 상태를 확인할 수 있고 어떤 쓰레드끼리 DeadLock이 발생했는지 편하게 확인할 수 있다.

 

 

'Java' 카테고리의 다른 글

Java 배열에 대해서  (0) 2021.08.27
자바 String 클래스에 대해서  (1) 2021.08.27
자바 - enum  (0) 2020.09.01
Executor 인터페이스  (0) 2020.08.22
자바- Optional  (0) 2020.08.20

댓글