SynchronizedList / CopyOnWriteArrayList

Tech/Java 2023. 6. 2. 06:16
728x90
728x90

[Java] 자바에서의 스레드 안전(Thread Safe)과 모니터(monitor)

연관 게시물 https://mag1c.tistory.com/364 스레드 안전 - Thread Safe 연관 게시물 https://mag1c.tistory.com/365 [Java] 자바에서의 스레드 안전(Thread Safe)과 모니터(monitor) 자바에서의 Thread-Safe 1. Lock synchronized 아래

mag1c.tistory.com

스레드 안전 - Thread Safe

연관 게시물 https://mag1c.tistory.com/365 [Java] 자바에서의 스레드 안전(Thread Safe)과 모니터(monitor) 자바에서의 Thread-Safe 1. Lock synchronized 아래 코드는 Synchronized 키워드를 사용하여 스레드의 안전성을 보

mag1c.tistory.com

 


 
 
 
멀티 쓰레드 환경에서, 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/
 
 
 

 

728x90
300x250
mag1c

mag1c

2년차 주니어 개발자.

방명록