221025 - DeakLock, 데드락

Jongleee·2022년 10월 25일
1

TIL

목록 보기
87/737

Thread DeadLock 이란?

멀티 쓰레드 프로그래밍에서 동기화를 통해 락을 획득하여 동일한 자원을 여러 곳에서 함부로 사용하지 못하도록 함

이는 두 가지 이상의 작업을 왔다갔다 하면서 실행하여 동시에 진행되는 것처럼 멀티 쓰레드를 구현하였기 때문임

하지만 두 개의 쓰레드에서 서로가 가지고 있는 락이 해제되기를 기다리는 상태가 생길 수 있으며 이러한 상태를 교착상태(deadlock) 이라고 함

즉, 어떤 작업도 실행되지 못하고 서로 상대방의 작업이 끝나기만 바라는 무한정 대기 상태

DeakLock 발생 조건

  • 상호 배제 (Mutual Exclusion) : 한 자원에 대해 여러 쓰레드 동시 접근 불가

  • 점유와 대기 (Hold and Wait) : 자원을 가지고 있는 상태에서 다른 쓰레드가 사용하고 있는 자원 반납을 기다리는 것

  • 비선점 (Non Preemptive) : 다른 쓰레드의 자원을 실행 중간에 강제로 가져올 수 없음

  • 환형대기 (Circle Wait) : 각 쓰레드가 순환적으로 다음 쓰레드가 요구하는 자원을 가지고 있는 것

위의 4가지 조건을 모두 충족할 경우 데드락이 발생.
즉, 위 4가지 중 하나라도 충족하지 않을 경우 데드락을 해결할 수 있다는 뜻.

DeakLock 실습 코드

public class Main {

    public static Object object1 = new Object();
    public static Object object2 = new Object();

    public static void main(String[] args) {
        FirstThread thread1 = new FirstThread();
        SecondThread thread2 = new SecondThread();

        thread1.start();
        thread2.start();

    }

    private static class FirstThread extends Thread{
        @Override
        public void run() {
            synchronized (object1){
                System.out.println("First Thread has object1's lock");

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("First Thread want to have object2's lock. so wait");

                synchronized (object2){
                    System.out.println("First Thread has object2's lock too");
                }
            }
        }
    }

    private static class SecondThread extends Thread{
        @Override
        public void run() {
            synchronized (object2){
                System.out.println("Second Thread has object2's lock");

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Second Thread want to have object1's lock, so wait");

                synchronized (object1){
                    System.out.println("Second Thread has object1's lock too");
                }
            }
        }
    }
}
  • 상호 배제 : object1과 object2 객체에 대해서 동시에 쓰레드가 사용할 수 없도록 함

  • 점유와 대기 : FirstThread에서는 object1의 락을 가지고 있으면서 object2에 대한 락을 원하고, SecondThread는 object2에 대한 락을 가지고 있으면서 object1의 락을 획득하기를 원함.

  • 비선점 : 쓰레드의 우선순위의 기본값은 NORM_PRIORITY로 동일하게 설정됨.

  • 환형대기 : FirstThread는 SecondThread의 object2 객체의 락을 대기하고 SecondThread는 FirstThread의 object1 객체의 락을 대기.

데드락 해결 방법

  1. 예방: 네 가지 조건 중 하나만을 해결한다.
  2. 회피: 발생조건을 없애기보다 발생하지 않도록 알고리즘을 적용하는 것이다. 자원할당 그래프 알고리즘과 은행원 알고리즘이 있다.
  3. 회복: 교착상태가 발생하는 것을 아예 막지 않고, 만약 교착상태가 발생하면 발생 이후에 문제를 해결하는 것이다.
  4. 무시: 교착상태를 해결할 때도 context switch에 의한 오버헤드로 성능 저하가 생긴다. 해결할때의 성능 저하가 교착상태에 의한 성능 저하보다 더 큰 경우 그냥 무시한다.

0개의 댓글