>

교착 상태 예제를 찾고 있었고이 코드를 우연히 발견했습니다 :

package com.example.thread.deadlock._synchronized;
public class BankAccount {
    double balance;
    int id;
    BankAccount(int id, double balance) {
        this.id = id;
        this.balance = balance;
    }
    void withdraw(double amount) {
        // Wait to simulate io like database access ...
        try {Thread.sleep(10l);} catch (InterruptedException e) {}
        balance -= amount;
    }
    void deposit(double amount) {
        // Wait to simulate io like database access ...
        try {Thread.sleep(10l);} catch (InterruptedException e) {}
        balance += amount;
    }
    static void transfer(BankAccount from, BankAccount to, double amount) {
        synchronized(from) {
            from.withdraw(amount);
            synchronized(to) {
                to.deposit(amount);
            }
        }
    }
    public static void main(String[] args) {
        final BankAccount fooAccount = new BankAccount(1, 100d);
        final BankAccount barAccount = new BankAccount(2, 100d);
        new Thread() {
            public void run() {
                BankAccount.transfer(fooAccount, barAccount, 10d);
            }
        }.start();
        new Thread() {
            public void run() {
                BankAccount.transfer(barAccount, fooAccount, 10d);
            }
        }.start();
    }
}

transfer 를 어떻게 바꾸겠습니까  교착 상태를 유발하지 않도록 방법? 첫 번째 생각은 모든 계정에 대해 공유 잠금을 만드는 것이지만 물론 모든 동시성을 죽일 것입니다. 거래와 관련된 두 개의 계정 만 잠그고 다른 계정에는 영향을 미치지 않는 좋은 방법이 있습니까?


  • 답변 # 1

    멀티 록 상황에서 교착 상태를 피하는 한 가지 방법은 항상 같은 순서로 개체를 잠그는 것입니다.

    이 경우 모든 BankAccount 에 대해 총 주문을 생성한다는 의미입니다.  사물. 운 좋게도 사용할 수있는 ID가 있으므로 항상 하위 ID를 먼저 잠근 다음 다른 동기화 된 블록 내에서 상위 ID를 잠글 수 있습니다.

    이것은 BankAccount 가 없다고 가정합니다.  동일한 ID를 가진 객체이지만 합리적인 가정처럼 보입니다.

  • 답변 # 2

    네스트 대신 두 개의 동기화 된 블록을 별도로 사용하십시오.

    synchronized(from){
        from.withdraw(amount);
    }
    synchronized(to){
        to.deposit(amount);
    }
    
    

    from.withdraw(amount) 이후   from 의 잠금이라고합니다.   to 를 잠그기 전에 해제됩니다.

  • 이전 arrays - 재귀 단위없는 요소 유형
  • 다음 routes - 스프링 부트 - 코드 에서이 bean을 찾을 수있는 곳 콩인가요?