자바 잠 금 분리

4352 단어 자바
읽 기와 쓰기 자물쇠 사상의 연장 은 바로 자물쇠 분리 이다.읽 기와 쓰기 자 물 쇠 는 읽 기와 쓰기 조작 기능 에 따라 효과 적 인 자 물 쇠 를 분리 했다.응용 프로그램의 기능 특징 에 따라 유사 한 분리 사상 을 사용 해도 독점 자 물 쇠 를 분리 할 수 있다.전형 적 인 응용 프로그램 은 java. util. concurrent. LinkedBlockingQueue 입 니 다.    링크 드 BlockingQueue 의 실현 중 입 니 다.take () 와 put () 함 수 는 각각 대기 열 에서 데 이 터 를 가 져 오고 대기 열 에 데 이 터 를 추가 하 는 기능 을 실현 합 니 다.이 두 조작 은 모두 현재 대기 열 을 수정 하 는 작업 이지 만 링크 드 BlockingQueue 는 링크 를 바탕 으로 이 루어 진 것 이기 때문에 이 두 조작 은 각각 이 링크 의 전단 과 끝 에 대응 하고 이론 적 으로 볼 때 이 두 조작 은 충돌 하지 않 습 니 다.   독점 자 물 쇠 를 사용 하면 이 두 조작 이 진 행 될 때 독점 자 물 쇠 를 가 져 오 라 고 요구한다. 그러면 이 두 조작 은 진정한 의미 의 병발, 치열 한 자물쇠 경쟁 을 실현 하지 못 하고 시스템 성능 에 영향 을 줄 수 없다.     jdk 에 서 는 이러한 방식 을 사용 하지 않 았 습 니 다. 대신 두 개의 서로 다른 자물쇠 가 take () 와 put () 작업 을 분리 하 였 습 니 다.
  

      /** Lock held by take, poll, etc */
    private final ReentrantLock takeLock = new ReentrantLock();

    /** Wait queue for waiting takes */
    private final Condition notEmpty = takeLock.newCondition();

    /** Lock held by put, offer, etc */
    private final ReentrantLock putLock = new ReentrantLock(); 
   

 
    상기 코드 는 takeLock 과 putLock 을 정의 합 니 다. 그들 은 각각 take () 와 put () 작업 에 대응 합 니 다. take () 와 put () 는 서로 독립 되 고 take (0 과 take () 경쟁 자물쇠, put () 와 put () 경쟁 자물쇠 입 니 다. 
 

       public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();//         
        try {
            try {
                while (count.get() == 0)
                    notEmpty.await();
            } catch (InterruptedException ie) {
                notEmpty.signal(); // propagate to a non-interrupted thread
                throw ie;
            }

            x = extract();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }
   

  

public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        // Note: convention in all put/take/etc is to preset
        // local var holding count  negative to indicate failure unless set.
        int c = -1;
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();//        
        try {
            /*
             * Note that count is used in wait guard even though it is
             * not protected by lock. This works because count can
             * only decrease at this point (all other puts are shut
             * out by lock), and we (or some other waiting put) are
             * signalled if it ever changes from
             * capacity. Similarly for all other uses of count in
             * other wait guards.
             */
            try {
                while (count.get() == capacity)
                    notFull.await();
            } catch (InterruptedException ie) {
                notFull.signal(); // propagate to a non-interrupted thread
                throw ie;
            }
            insert(e);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
    }


  개념 이 너무 많아 오히려 이해 하기 어렵다. 여기 서 간단하게 자물쇠 분리 와 세그먼트 자 물 쇠 를 말한다.  우 리 는 Concurrent HashMap 과 같은 데이터 구 조 를 분석 합 니 다. 잠 금 분리 체 제 는 하나의 HashMap 을 여러 개의 segement 로 나 누 어 모든 segement 의 쓰기 작업 에 자 물 쇠 를 채 우 는 것 입 니 다. 그의 get ()조작 은 잠 겨 있 지 않 습 니 다. 구체 적 인 사상 은 모든 hash 슬롯 의 링크 의 머리 부분 을 final 로 설정 하 는 것 입 니 다. hash 슬롯 의 링크 조작 은 머리 에서 만 처리 할 수 있 습 니 다. 그러면 읽 기 가 일치 하지 않 는 상황 이 발생 하지 않 습 니 다. 이 원 리 는 소스 코드 를 보 는 것 이 좋 습 니 다. 비교적 뚜렷 합 니 다.

좋은 웹페이지 즐겨찾기