ArrayBlockingQueue에서 최종 멤버 필드를 로컬 최종 변수에 복사하는 이유는 무엇입니까? lock.lock();

에서 ArrayBlockingQueue, 잠금을 필요로하는 모든 방법은 로컬에 복사 final호출하기 전에 변수 lock().

public boolean offer(E e) {
    if (e == null) throw new NullPointerException();
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count == items.length)
            return false;
        else {
            insert(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

필드 가 있을 때 this.lock지역 변수 에 복사 할 이유 가 있습니까?lockthis.lockfinal

또한 작업 E[]하기 전에 의 로컬 사본도 사용 합니다.

private E extract() {
    final E[] items = this.items;
    E x = items[takeIndex];
    items[takeIndex] = null;
    takeIndex = inc(takeIndex);
    --count;
    notFull.signal();
    return x;
}

최종 필드를 지역 최종 변수에 복사하는 이유가 있습니까?



답변

클래스의 저자 인 Doug Lea가 사용하기를 좋아하는 극단적 인 최적화입니다. 다음 은 core-libs-dev 메일 링 목록 의 최근 스레드 에 대한 게시물 이 정확한 주제에 대해 귀하의 질문에 꽤 잘 대답합니다.

게시물에서 :

… 로컬로 복사하면 가장 작은 바이트 코드가 생성되며, 저수준 코드의 경우 기계에 조금 더 가까운 코드를 작성하는 것이 좋습니다.


답변

이 스레드 는 몇 가지 답변을 제공합니다. 실질적으로 :

  • 컴파일러는 메서드 내에서 최종 필드가 변경되지 않는다는 것을 쉽게 증명할 수 없습니다 (반사 / 직렬화 등으로 인해)
  • 대부분의 최신 컴파일러는 실제로 시도하지 않으므로 캐시 미스 또는 페이지 오류로 이어질 수있는 최종 필드를 사용할 때마다 다시로드해야합니다.
  • 로컬 변수에 저장하면 JVM이 하나의로드 만 수행합니다.


답변