집합 프레임 워 크 깊이 있 는 CopyOnWriteArray List 소스 분석
CopyonWriteArrayList 는 ArrayList 의 안전 한 스 레 드 변종 입 니 다.
CopyOn Write Array List 와 Array List 는 배열 을 복사 하고 자 물 쇠 를 추가 할 지 여부 에 달 려 있다.
CopyOnWriteArrayList 는 말 그대로 쓰기 시 복 제 된 ArrayList 로,용기 의 요 소 를 수정 할 때 원 배열 에서 직접 수정 하 는 것 이 아니 라 한 배열 을 복사 한 다음 복 사 된 배열 에서 수정 하고 수정 한 후 이 를 원 배열 의 인용 에 할당 한 다 는 뜻 이다.이렇게 하면 읽 기와 쓰기 의 분 리 를 나타 내 고 언제든지 용기 에 대해 읽 을 수 있다.
구성원 변수
여기 서 흔히 볼 수 있 는 몇 가지 특성 을 분석 해 보 자.
transient final ReentrantLock lock = new ReentrantLock();
// CopyOnWriteArrayList , 。
private volatile transient Object[] array;
이것 이 바로 원수 그룹 입 니 다.우 리 는 Array List 와 다른 점 은 volatile 속성 을 증가 시 켰 다 는 것 을 발 견 했 습 니 다.
이게 무슨 소 용이 있 습 니까?
Volaile 은 약 한 단계 의 synchronized 에 해당 하 며 가시 성 을 제공 합 니 다.다 중 스 레 드 실행 환경 에서 모든 스 레 드 를 볼 수 있 습 니 다.이것 은 모든 스 레 드 가 얻 은 데이터 가 일치 하 는 것 을 보장 합 니 다.
자 물 쇠 는 두 가지 단계 의 메커니즘 을 제공 했다.상호 배척 과 가시
서로 배척 하 는 것 은 한 스 레 드 가 수 정 된 데 이 터 를 수정 할 때 다른 스 레 드 는 이 데 이 터 를 방문 할 수 없다 는 것 이다.
이 를 통 해 알 수 있 듯 이 한 스 레 드 가 데 이 터 를 수정 할 때 다른 스 레 드 가 받 은 값 은 모두 일치 하 다.모든 스 레 드 가 volatile 의 최신 값 을 자동 으로 가 져 올 수 있다 는 것 이다.
그래서 synchronized 는 array 가 쓸 때의 원자 성 을 확보 하고 volatile 은 array 의 가시 성 을 확보한다 고 할 수 있 습 니 다.
----------------------------------------------------------------------------------------------------------------------------
//
final Object[] getArray() {
return array;
}
//
final void setArray(Object[] a) {
array = a;
}
읽 기:
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return (E)(getArray()[index]);
}
, 。
쓰기:
//
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
//
Object oldValue = elements[index];
if (oldValue != element) {
int len = elements.length;
//
Object[] newElements = Arrays.copyOf(elements, len);
//
newElements[index] = element;
//
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return (E)oldValue;
} finally {
lock.unlock();
}
}
//
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
<span style="white-space:pre"> </span>//
Object[] newElements = Arrays.copyOf(elements, len + 1);
<span style="white-space:pre"> </span>//
newElements[len] = e;
<span style="white-space:pre"> </span>//
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
//
public E remove(int index) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
<span style="white-space:pre"> </span>//
Object oldValue = elements[index];
int numMoved = len - index - 1;
if (numMoved == 0)
<span style="white-space:pre"> </span>//
setArray(Arrays.copyOf(elements, len - 1));
else {
<span style="white-space:pre"> </span> //
Object[] newElements = new Object[len - 1];
<span style="white-space:pre"> </span>// 0 index
System.arraycopy(elements, 0, newElements, 0, index);
<span style="white-space:pre"> </span> //
System.arraycopy(elements, index + 1, newElements, index,
numMoved);
<span style="white-space:pre"> </span> //
setArray(newElements);
}
return (E)oldValue;
} finally {
lock.unlock();
}
}
위의 세 가지 업데이트,추가,삭제 방법 을 보면 CopyOn Write Array List 는 원래 배열 을 수정 하 는 과정 에서 Array List 보다 두 가지 일 을 더 한 것 을 발견 했다.
1.잠 금 추가:내 가 배열 을 수정 할 때 다른 사람 이 수정 할 수 없 도록 보장 합 니 다.
2.복사 배열:어떤 방법 이 든 복사 배열 이 필요 합 니 다.
위의 두 가지 일 은 CopyOn Write Array List 가 다 중 스 레 드 환경 에서 자 유 롭 게 대응 할 수 있 도록 확보 했다.
----------------------------------------------------------------------------------------------------------------------------------------------------
교체 기:
CopyOn WriteArray List 의 교체 기 는 빠 른 실패 가 아 닙 니 다.즉,Concurrent ModificationException 이상 을 던 지지 않 습 니 다.수정 할 때 복사 배열 에 영향 을 주지 않 았 기 때문이다.교체 기 에 잠 금 장치 가 없 음 을 알 수 있 기 때문에 읽 기 만 제공 하고 수정 과 삭 제 를 추가 하 는 것 은 지원 되 지 않 습 니 다.
public ListIterator<E> listIterator() {
return new COWIterator<E>(getArray(), 0);
}
private static class COWIterator<E> implements ListIterator<E> {
//
private final Object[] snapshot;
//
private int cursor;
private COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements;
}
public boolean hasNext() {
return cursor < snapshot.length;
}
public boolean hasPrevious() {
return cursor > 0;
}
public E next() {
if (! hasNext())
throw new NoSuchElementException();
return (E) snapshot[cursor++];
}
public E previous() {
if (! hasPrevious())
throw new NoSuchElementException();
return (E) snapshot[--cursor];
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
//
public void remove() {
throw new UnsupportedOperationException();
}
//
public void set(E e) {
throw new UnsupportedOperationException();
}
//
public void add(E e) {
throw new UnsupportedOperationException();
}
}
CopyOnWriteArrayList 의 부족 함:
데이터 일치 성 문제:한 스 레 드 가 수정 되 고 있 고 다른 스 레 드 가 지금 오래된 데 이 터 를 읽 습 니 다.즉,데이터 의 일치 성 을 보장 할 수 없습니다.
메모리 문제:
추가,수정,삭제 작업 에서 대량의 복사 배열 이 있 습 니 다.메모리 가 시간 이 지나 면 메모리 에 많은 새로운 배열 이 생 겨 서 일련의 young 을 미리 촉발 합 니 다. GC 와 Full GC 는 CopyOnWriteArrayList 가 읽 기 에 더 적합 하고 대량의 수정 에 적합 하지 않다 는 것 을 설명 했다.
참고:
동시 다발 얘 기.-자바 의 Copy-On-Write 용기.
CopyOnWriteArrayList 소스 코드 를 보고
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.