어뗜 경우에 데드락과 같이 활동성에 문제가 되는지 살펴보고, 이런 상황을 미연에 방지하는 방법

10.1 데드락

10.1.1 락 순서에 의한 데드락

[예시] 2개의 스레드가 서로 다른 순서로 락을 확보할 때 발생 가능한 데드락

public class LeftRightDeadlock {
    private final Object left = new Object();
    private final Object right = new Object();

    public void leftRight() {
        synchronized (left) {
            synchronized (right) {
                doSomething();
            }
        }
    }

    public void rightLeft() {
        synchronized (right) {
            synchronized (left) {
                doSomethingElse();
            }
        }
    }

    void doSomething() {
    }

    void doSomethingElse() {
    }
}

Untitled

10.1.2 동적인 락 순서에 의한 데드락

프로그램을 작성할 때 데드락을 방지할 수 있을 만큼 락을 사용하는 순서를 충분히 조절하지 못할 수도 있다.

[예시] 함수에 넘겨주는 인자의 순서에 따라 락 순서가 달라질 때 발생 가능한 데드락

public static void transferMoney(Account fromAccount,
                                 Account toAccount,
                                 DollarAmount amount)
        throws InsufficientFundsException {
    synchronized (fromAccount) {
        synchronized (toAccount) {
            if (fromAccount.getBalance().compareTo(amount) < 0)
                throw new InsufficientFundsException();
            else {
                fromAccount.debit(amount);
                toAccount.credit(amount);
            }
        }
    }
}
- 스레드 A: transferMoney(myAccount, yourAccount, 10); // myAccount -> yourAccount 
- 스레드 B: transferMoney(yourAccount, myAccount, 20); // yourAccount -> myAccount