并发 - Java的AQS.Node源码疑惑
大家讲道理
大家讲道理 2017-04-17 18:00:30
0
2
786

AbstractQueuedSynchronizerNode内部类中,对volatile Node prev成员变量获取方法predecessor()如下

   
    final Node predecessor() throws NullPointerException {
        Node p = prev;
        if (p == null)
            throw new NullPointerException();
        else
            return p;
    }

在源码中,这里对volatile类型的成员变量prev的返回,是先把他赋值给一个中间变量p,然后拿p返回。
这种设计在AQS的源码中很多地方都有涉及到,包括在其它源码中也经常看到对volatile类型的变量先赋值给另外一个变量,然后把这个变量返回.
这样设计的目的是什么?

大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

모든 응답(2)
迷茫

으아악

불필요해 보이는 지역 변수 결과에 주목하세요. 이것의 효과는 도우미가 이미 초기화된 경우(즉, 대부분의 경우) 휘발성 필드가 한 번만 액세스된다는 것입니다("return helper;" 대신 "return result;"로 인해). 메소드의 전체 성능이 25% 정도 향상됩니다.[6]

도우미 개체가 정적(클래스 로더당 하나)인 경우 대안은 요청 시 초기화입니다. 홀더 관용구[7](이전에 인용된 텍스트의 목록 16.6[8] 참조)

---------위키피디아

伊谢尔伦

predecessor() 방식에서는 Node p의 효과가 그다지 뚜렷하지 않습니다. 좀 더 극단적인 예를 들어보겠습니다.

으아악

100개의 스레드 호출이 prev의 값을 변경한다고 가정하면 #L1과 #L4 사이에서 공유 변수 -- prev에 대한 모든 변경 사항은 ExtremePredecessor()에 표시됩니다.
다음과 같은 문제가 있습니다.

  • 은 동기화 잠금과 매우 유사합니다. prev에 대한 동기 업데이트는 전체 대기열에 병목 현상을 발생시킵니다.

  • #L1과 #L4 사이의 prev 값은 다른 스레드에서 변경했기 때문에 일치하지 않을 수 있습니다. 이로 인해 코드를 이해하기가 훨씬 더 어려워집니다.

Node p = prev;을 사용하면 #L0 이후에는 p의 값을 동기화할 필요가 없습니다. p #L1부터 #L4까지 일관됩니다.

volatile의 경우
Java 언어 사양 휘발성 키워드
https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls- 8.3을 참조하세요. .1.4

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!