JDK 소스 코드가 '휘발성'인스턴스의 '최종'복사본을 사용하는 이유
ConcurrentHashMap에 대한 JDK의 소스 코드를 읽었습니다.
그러나 다음 코드는 나를 혼란스럽게 만들었습니다.
public boolean isEmpty() {
final Segment<K,V>[] segments = this.segments;
...
}
내 질문은 :
"this.segments"는 다음과 같이 선언됩니다.
final Segment<K,V>[] segments;
따라서 여기에서 메서드의 시작 부분에서 동일한 유형 참조를 선언하고 동일한 메모리를 가리 킵니다.
저자는 왜 이렇게 썼습니까? 왜 그들은 this.segments를 직접 사용하지 않았습니까? 이유가 있나요?
이것은 volatile
변수를 포함하는 잠금없는 코드의 전형적인 관용구 입니다. 첫 번째 줄에서 volatile
한 번 읽은 다음 작업합니다. 그 동안 다른 스레드가을 업데이트 할 수 volatile
있지만 처음에 읽은 값에만 관심이 있습니다.
또한 문제의 멤버 변수가 휘발성이 아니라 최종적인 경우에도 스택 위치에서 읽는 것이 임의의 힙 위치에서 읽는 것보다 캐시 친화적이므로이 관용구는 CPU 캐시와 관련이 있습니다. 또한 로컬 변수가 CPU 레지스터에 바인딩 될 가능성이 더 높습니다.
후자의 경우 JIT 컴파일러가 일반적으로 이러한 문제를 처리하기 때문에 실제로 논란이 있지만 Doug Lea는 일반적인 원칙을 고수하는 사람 중 하나입니다.
성능을 고려한 것이므로 필드 값을 한 번만 검색하면됩니다.
Joshua Bloch의 효과적인 자바에서 단일 관용구를 참조 할 수 있습니다.
그의 싱글 톤은 다음과 같습니다.
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) {
synchronized(this) {
result = field;
if (result == null)
field = result = computeFieldValue();
}
}
return result;
}
그리고 그는 다음과 같이 썼습니다.
이 코드는 약간 복잡하게 보일 수 있습니다. 특히 지역 변수 결과에 대한 필요성이 명확하지 않을 수 있습니다. 이 변수가하는 일은 필드가 이미 초기화 된 일반적인 경우에 한 번만 읽히도록하는 것입니다. 꼭 필요한 것은 아니지만 이는 성능을 향상시킬 수 있으며 낮은 수준의 동시 프로그래밍에 적용되는 표준에 의해 더욱 우아합니다. 내 컴퓨터에서 위의 방법은 로컬 변수가없는 명백한 버전보다 약 25 % 빠릅니다 .
바이트 코드 크기를 줄일 수 있습니다. 로컬 변수에 액세스하는 것이 인스턴스 변수에 액세스하는 것보다 바이트 코드가 더 짧습니다.
런타임 최적화 오버 헤드도 줄일 수 있습니다.
그러나 이들 중 어느 것도 중요하지 않습니다. 코드 스타일에 관한 것입니다. 인스턴스 변수에 익숙하다면 꼭. Doug Lea는 아마도 지역 변수를 다루는 것이 더 편할 것입니다 .
'Programing' 카테고리의 다른 글
음수가 될 수없는 값에 대해 C #에서 uint를 사용해야합니까? (0) | 2020.10.22 |
---|---|
자산 (이미지, CSS, JS)에 대한 명명 규칙? (0) | 2020.10.22 |
Shiny에서 '최대 업로드 크기 초과'제한을 변경하고 사용자 파일 입력을 저장하는 방법은 무엇입니까? (0) | 2020.10.22 |
클라이언트 3000을 확인할 수 없습니다. (0) | 2020.10.22 |
저장소 URL을 변경 한 후 Capistrano 배포가 실패 함 (0) | 2020.10.21 |