자바 보안 인 코딩 안내 잠 금 dead lock

5714 단어 자바자물쇠
다른 잠 금 순서
우 리 는 서로 다른 잠 금 순서 의 예 를 살 펴 보 자.

public class DiffLockOrder {

    private int amount;

    public DiffLockOrder(int amount){
       this.amount=amount;
    }

    public void transfer(DiffLockOrder target,int transferAmount){
        synchronized (this){
            synchronized (target){
                if(amount< transferAmount){
                    System.out.println("    !");
                }else{
                    amount=amount-transferAmount;
                    target.amount=target.amount+transferAmount;
                }
            }
        }
    }
}
위의 예 에서 저 희 는 계좌 이체 과정 을 모 의 했 습 니 다.amount 는 사용자 의 잔액 을 표시 합 니 다.transfer 는 현재 계 정의 일부 금액 을 목표 대상 으로 이전 하 는 데 사용 합 니 다.
transfer 과정 에서 두 계 정 이 다른 사람 에 게 수정 되 지 않도록 두 개의 synchronized 키 워드 를 사용 하여 각각 transfer 대상 과 대상 을 잠 금 합 니 다.
문제 가 없 는 것 같 지만 호출 과정 에서 transfer 의 순 서 는 변 화 를 보 낼 수 있 습 니 다.

DiffLockOrder account1 = new DiffLockOrder(1000);
DiffLockOrder account2 = new DiffLockOrder(500);

Runnable target1= ()->account1.transfer(account2,200);
Runnable target2= ()->account2.transfer(account1,100);
new Thread(target1).start();
new Thread(target2).start();
위의 예 에서 우 리 는 두 개의 account 를 정의 한 다음 에 두 계 정 이 서로 이 체 를 하면 마지막 에 서로 잠 겨 있 고 마지막 에 잠 겨 있 을 수 있 습 니 다.
private 클래스 변 수 를 사용 합 니 다.
두 개의 sync 를 사용 하면 순서 적 인 문제 가 있 습 니 다.하나의 sync 만으로 모든 인 스 턴 스 에서 동기 화 할 수 있 는 방법 은 없 습 니까?
있 습 니 다.우 리 는 private 의 클래스 변 수 를 사용 할 수 있 습 니 다.클래스 변 수 는 모든 인 스 턴 스 에서 공유 되 기 때문에 한 번 의 sync 로 충분 합 니 다.

public class LockWithPrivateStatic {

    private int amount;

    private static final Object lock = new Object();

    public LockWithPrivateStatic(int amount){
       this.amount=amount;
    }

    public void transfer(LockWithPrivateStatic target, int transferAmount){
        synchronized (lock) {
            if (amount < transferAmount) {
                System.out.println("    !");
            } else {
                amount = amount - transferAmount;
                target.amount = target.amount + transferAmount;
            }
        }
    }
}
같은 Order 사용 하기
우리 가 자물쇠 가 생기 는 이 유 는 자물쇠 의 순 서 를 제어 할 수 없 기 때문이다.만약 우리 가 자물쇠 의 순 서 를 제어 할 수 있다 면 자물쇠 가 생기 지 않 을 것 이다.
이 생각 을 가지 고 우 리 는 대상 에 게 id 필드 를 추가 합 니 다.

private final long id; //   ID,    
private static final AtomicLong nextID = new AtomicLong(0); //     ID

public DiffLockWithOrder(int amount){
    this.amount=amount;
    this.id = nextID.getAndIncrement();
}
대상 을 초기 화 할 때,우 리 는 static 의 AtomicLong 클래스 를 사용 하여 모든 대상 에 게 유일한 ID 를 생 성 합 니 다.
transfer 를 할 때 우 리 는 먼저 두 대상 의 ID 크기 를 비교 한 다음 에 ID 에 따라 정렬 하고 마지막 에 설치 순서에 따라 자 물 쇠 를 추가 합 니 다.이렇게 하면 순 서 를 확보 하여 자물쇠 가 잠 겨 있 는 것 을 피 할 수 있다.

public void transfer(DiffLockWithOrder target, int transferAmount){
    DiffLockWithOrder fist, second;

    if (compareTo(target) < 0) {
        fist = this;
        second = target;
    } else {
        fist = target;
        second = this;
    }

    synchronized (fist){
        synchronized (second){
            if(amount< transferAmount){
                System.out.println("    !");
            }else{
                amount=amount-transferAmount;
                target.amount=target.amount+transferAmount;
            }
        }
    }
}
소유 한 자 물 쇠 를 풀다
자 물 쇠 는 서로 에 게 점용 을 요청 하 는 자물쇠 이지 만 상대방 의 자 물 쇠 는 계속 풀 리 지 않 았 습 니 다.자 물 쇠 를 얻 지 못 하면 이미 점용 한 자 물 쇠 를 자동 으로 풀 어도 자물쇠 문 제 를 해결 할 수 있 지 않 을까요?
ReentrantLock 은 try Lock()방법 이 있 기 때문에 우 리 는 이 방법 으로 자 물 쇠 를 얻 을 수 있 는 지,얻 지 못 하면 이미 차지 한 자 물 쇠 를 풀 수 있 는 지 를 판단 할 수 있 습 니 다.
저 희 는 ReentrantLock 을 사용 하여 이 예 를 완성 합 니 다.

public class DiffLockWithReentrantLock {

    private int amount;
    private final Lock lock = new ReentrantLock();

    public DiffLockWithReentrantLock(int amount){
        this.amount=amount;
    }

    private void transfer(DiffLockWithReentrantLock target, int transferAmount)
            throws InterruptedException {
        while (true) {
            if (this.lock.tryLock()) {
                try {
                    if (target.lock.tryLock()) {
                        try {
                            if(amount< transferAmount){
                                System.out.println("    !");
                            }else{
                                amount=amount-transferAmount;
                                target.amount=target.amount+transferAmount;
                            }
                            break;
                        } finally {
                            target.lock.unlock();
                        }
                    }
                } finally {
                    this.lock.unlock();
                }
            }
            //  sleep     ,        
            Thread.sleep(1000+new Random(1000L).nextInt(1000));
        }
    }

}
우 리 는 두 개의 try Lock 방법 을 while 순환 에서 자 물 쇠 를 얻 지 못 하면 반복 해서 옮 겨 다 닙 니 다.
이상 은 자바 보안 인 코딩 매 뉴 얼 의 잠 금 dead lock 에 대한 상세 한 내용 입 니 다.자바 보안 인 코딩 매 뉴 얼 의 잠 금 dead lock 에 관 한 자 료 는 다른 관련 글 을 주목 하 시기 바 랍 니 다!

좋은 웹페이지 즐겨찾기