programing

CopyOnWriteArrayList는 어떻게 스레드로부터 안전합니까?

sourcetip 2021. 1. 14. 23:43
반응형

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

반응형