CopyOnWriteArrayList는 어떻게 스레드로부터 안전합니까?
OpenJDK 소스 코드 를 살펴본 CopyOnWriteArrayList
결과 모든 쓰기 작업이 동일한 잠금으로 보호되고 읽기 작업이 전혀 보호되지 않는 것 같습니다. 내가 이해하는 바와 같이, JMM에서 변수에 대한 모든 액세스 (읽기 및 쓰기 모두)는 잠금으로 보호되어야합니다. 그렇지 않으면 재정렬 효과가 발생할 수 있습니다.
예를 들어 set(int, E)
메서드에는 다음 줄이 포함됩니다 (잠금 상태).
/* 1 */ int len = elements.length;
/* 2 */ Object[] newElements = Arrays.copyOf(elements, len);
/* 3 */ newElements[index] = element;
/* 4 */ setArray(newElements);
반면 get(int)
에이 방법은 return get(getArray(), index);
.
JMM에 대한 내 이해에서 이것은 get
문 1-4가 1-2 (new) -4-2 (copyOf) -3과 같이 재정렬되면 배열이 일관되지 않은 상태로 관찰 될 수 있음을 의미합니다 .
JMM을 잘못 이해했거나 CopyOnWriteArrayList
스레드로부터 안전한 이유에 대한 다른 설명 이 있습니까?
기본 배열 참조를 보면 volatile
. 쓰기 작업이 발생하면 (예 : 위의 추출에서)이 volatile
참조는를 통해 최종 문에서만 업데이트됩니다 setArray
. 이 시점까지 모든 읽기 작업은 배열 의 이전 복사본 에서 요소를 반환합니다 .
중요한 점은 배열 업데이트가 원자 적 작업 이므로 읽기는 항상 배열이 일관된 상태로 표시된다는 것입니다.
쓰기 작업에 대한 잠금 만 해제하면 읽기 처리량이 향상된다는 장점이 있습니다. 이는 CopyOnWriteArrayList
전체 목록을 복사하는 작업이 포함되므로 a에 대한 쓰기 작업 이 잠재적으로 매우 느릴 수 있기 때문 입니다.
배열 참조를 가져 오는 것은 원자 적 작업입니다. 따라서 독자는 상태가 일관된 방식으로 이전 어레이 또는 새 어레이를 볼 수 있습니다. ( set(int,E)
참조를 설정하기 전에 새 배열 내용을 계산하므로 서명이 만들어 질 때 배열이 일관됩니다.)
배열 참조 자체는 volatile
판독기가 참조 된 배열의 변경 사항을보기 위해 잠금을 사용할 필요가 없도록 표시됩니다 . (편집 : 또한 volatile
할당이 다시 정렬되지 않도록 보장하므로 배열이 일관성이없는 상태 일 때 할당이 수행됩니다.)
쓰기 잠금은 동시 수정을 방지하는 데 필요합니다. 이로 인해 어레이가 일관성없는 데이터를 보유하거나 변경 사항이 손실 될 수 있습니다.
참조 URL : https://stackoverflow.com/questions/2950871/how-can-copyonwritearraylist-be-thread-safe
'programing' 카테고리의 다른 글
콜론이있는 자바 스크립트 반환 (0) | 2021.01.14 |
---|---|
함수가 비동기인지 어떻게 알 수 있습니까? (0) | 2021.01.14 |
Android-화면이 아닌 휴대 전화 잠금 해제 이벤트 감지 (0) | 2021.01.14 |
Objective-C에서 연산자를 오버로드 할 수 있습니까? (0) | 2021.01.14 |
MySQL "주요 효율성"이란? (0) | 2021.01.14 |