멀티 쓰레드 환경에서, List를 사용하기 위해 SynchronizedList나 CopyOnWriteArrayList를 사용할 수 있다.
SynchronizedList
java.utils.Collections의 List를 상속받아 구현되어있으며, synchronized 키워드를 통해 thread-safe를 구현시킨다.
// java.util.Collections
...
static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
final List<E> list;
...
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public int indexOf(Object o) {
synchronized (mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized (mutex) {return list.lastIndexOf(o);}
}
...
}
CopyOnWriteArrayList
set, add과정에서 lock과 함께 array를 copy후 write하는 방식으로 처리하기 때문에
get을 수행할 때 thread-safe하게 조회가 가능하다.
// java.util.concurrent.CopyOnWriteArrayList
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8673264195747942595L;
final transient Object lock = new Object();
private transient volatile Object[] array;
...
public E get(int index) {
return elementAt(getArray(), index);
}
public E set(int index, E element) {
synchronized (lock) {
Object[] es = getArray();
E oldValue = elementAt(es, index);
if (oldValue != element) {
es = es.clone();
es[index] = element;
}
setArray(es);
return oldValue;
}
}
public boolean add(E e) {
synchronized (lock) {
Object[] es = getArray();
int len = es.length;
es = Arrays.copyOf(es, len + 1);
es[len] = e;
setArray(es);
return true;
}
}
...
}
SynchronizedList는 단순 synchronized 키워드를 사용한 동기화된 List이기 때문에 모든 읽기, 쓰기 동작에 lock이 걸린다. 때문에 읽기보다 쓰기 동작이 많고, 크기가 큰 리스트의 경우에 적합할 것이다.
CopyOnWriteArrayList는 set, add과정에서 lock과 함께 copy후 write하는 방식이기 때문에, 읽기 동작에서의 수행능력이 좋을 것이다. 또한 특유의 동작 방식때문에 쓰기 동작에서는 상당한 부하가 발생할 것이다.
SynchronizedList : read < write
CopyOnWriteArrayList : read > write
참조
https://taes-k.github.io/2021/12/26/synchronizedlist-copyonwritelist/
https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedList-java.util.List-
http://asuraiv.blogspot.com/2020/02/java-synchronizedlist-vs.html
https://jihyehwang09.github.io/2020/04/14/java-copyonwritearraylist/
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!