자바 의 부적 절 한 실행 순서 로 인 한 잠 금

2882 단어 Java자물쇠
우 리 는 자주 존재 하 는 계좌 이체 문 제 를 토론 합 시다.계좌 A 는 계좌 B 로 이체 해 야 합 니 다.이 체 를 하 는 과정 에서 A 와 B 가 다른 라인 에서 예상 치 못 한 조작 을 하지 않도록 하기 위해 우 리 는 A 와 B 에 자 물 쇠 를 채 운 다음 에 이 체 를 해 야 한다.우 리 는 이 체 를 하 는 코드 를 보 자.

public void transferMoneyDeadLock(Account from,Account to, int amount) throws InsufficientAmountException {
    synchronized (from){
        synchronized (to){
            transfer(from,to,amount);
        }
    }
}

private void transfer(Account from,Account to, int amount) throws InsufficientAmountException {
    if(from.getBalance() < amount){
        throw new InsufficientAmountException();
    }else{
        from.debit(amount);
        to.credit(amount);
    }
}
위의 프로그램 은 문제 가 없 는 것 같 습 니 다.from 과 to 에 자 물 쇠 를 채 워 주 었 기 때문에 프로그램 은 우리 의 요구 에 따라 완벽 하 게 실 행 될 수 있 을 것 입 니 다.
그러면 우리 가 다음 장면 을 고려한다 면:

A:transferMoneyDeadLock(accountA, accountB, 20)
B:transferMoneyDeadLock(accountB, accountA, 10)
A 와 B 가 동시에 실행 되면 A 는 accontA 의 자 물 쇠 를 얻 었 고 B 는 accontB 의 자 물 쇠 를 얻 었 을 수 있다.그래서 뒤의 코드 가 계속 실행 되 지 못 해 자물쇠 가 잠 겼 다.
이런 상황 에 대해 우 리 는 어떤 좋 은 방법 으로 처리 할 수 있 습 니까?
매개 변수 가 어떻게 전달 되 든 간 에 우 리 는 먼저 lock accontA 를 넣 고 lock accontB 를 넣 으 면 잠 금 문제 가 발생 하지 않 을 것 입 니 다.
코드 구현 을 살 펴 보 겠 습 니 다.

private void transfer(Account from,Account to, int amount) throws InsufficientAmountException {
    if(from.getBalance() < amount){
        throw new InsufficientAmountException();
    }else{
        from.debit(amount);
        to.credit(amount);
    }
}

public void transferMoney(Account from,Account to, int amount) throws InsufficientAmountException {

    int fromHash= System.identityHashCode(from);
    int toHash = System.identityHashCode(to);

    if(fromHash < toHash){
        synchronized (from){
            synchronized (to){
                transfer(from,to, amount);
            }
        }
    }else if(fromHash < toHash){
        synchronized (to){
            synchronized (from){
                transfer(from,to, amount);
            }
        }
    }else{
        synchronized (lock){
        synchronized (from) {
            synchronized (to) {
                transfer(from, to, amount);
            }
            }
        }
    }
}
위의 예 에서 저 희 는 System.identity Hash Code 를 사용 하여 두 계 정의 hash 값 을 얻 었 고 hash 값 의 크기 를 비교 하여 lock 의 순 서 를 선택 하 였 습 니 다.
만약 에 두 계 정의 hash 값 이 똑 같은 상황 에서 우 리 는 새로운 외부 lock 을 도입 하여 같은 시간 에 하나의 스 레 드 만 내부 방법 을 실행 할 수 있 도록 함으로써 작업 의 수행 을 확보 하고 잠 금 이 생기 지 않도록 합 니 다.
이상 은 자바 가 부당 한 실행 순서 로 인 한 잠 금 에 대한 상세 한 내용 입 니 다.자바 가 부당 한 실행 순서 로 인 한 잠 금 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기