CopyOnWriteArrayList
thread-safe한 ArrayList로 add, set 등의 수정 작업이 발생하면 원본 배열을 새 배열로 복사하는 방식으로 동작함
이 방식은 비용이 많이 들긴 하지만 다음의 경우에 유용함
- 순회 연산(traversal operation)이 수정 연산보다 많은 경우 (수정 연산이 많은 경우엔 성능 저하 발생)
- 순회 연산을 동기화할 수 없는 경우
- 동시 스레드 간의 간섭을 방지하고 싶은 경우
CopyOnWriteArrayList의 iterator 메서드는 “snapshot” 개념처럼 iterator 생성된 시점의 배열 상태를 참조함
iterator가 동작하는 동안에는 배열이 변경되지 않고 간섭되지 않게 함으로써 iterator가 ConcurrentModificationException를 던지지 않도록 보장함
또한 iterator에서 수정 작업을 지원하지 않으므로 호출하면 UnsupportedOperationException를 터뜨림
final transient Object lock = new Object();
public E set(int index, E element) {
synchronized (lock) {
...
}
}
public boolean add(E e) {
synchronized (lock) {
...
}
}
public E remove(int index) {
synchronized (lock) {
...
}
}
static final class COWIterator<E> implements ListIterator<E> {
private final Object[] snapshot;
private int cursor;
public void add(E e) {
throw new UnsupportedOperationException();
}
}
var list = new CopyOnWriteArrayList<Integer>();
list.add(1);
list.add(2);