안드로이드/에러

[Android] ArrayList에서 ConcurrentModificartionException 발생

코딩하는후운 2024. 9. 20. 16:10
반응형

ArrayList에서 add와 remove가 동시에 발생하면서 ConcurrentModificartionException가 발생 하였다.

ConcurrentModificationException은 여러 스레드가 동시에 리스트를 수정하려고 할 때 발생

해결 방안

1. Collections.synchronizedList 사용

동기화된 리스트를 생성할 수 있습니다. 이 리스트는 모든 접근이 동기화되어 있어 여러 스레드가 동시에 접근해도 안전합니다.

val syncList = Collections.synchronizedList(mutableListOf<String>())

synchronized(syncList) {
    // 리스트에 요소 추가
    syncList.add("example")
    // 리스트에서 요소 제거
    syncList.remove("example")
}

 

2. CopyOnWriteArrayList 사용

CopyOnWriteArrayList는 읽기 작업이 많고 쓰기 작업이 적은 상황에 적합합니다. 이 리스트는 각 쓰기 작업에서 새로운 배열을 생성하므로 쓰기 작업이 빈번하지 않은 경우 유용합니다.

val cowList = CopyOnWriteArrayList<String>()

// 리스트에 요소 추가
cowList.add("example")
// 리스트에서 요소 제거
cowList.remove("example")

3.ReentrantLock 사용

ReentrantLock을 사용하여 수동으로 동기화하는 방법도 있습니다. 이 방법은 더 세밀한 제어가 가능하지만 코드가 복잡해질 수 있습니다.

import java.util.concurrent.locks.ReentrantLock

val list = mutableListOf<String>()
val lock = ReentrantLock()

lock.lock()
try {
    // 리스트에 요소 추가
    list.add("example")
    // 리스트에서 요소 제거
    list.remove("example")
} finally {
    lock.unlock()
}

4. ConcurrentLinkedQueue 사용

만약 순서가 중요하지 않다면 ConcurrentLinkedQueue와 같은 병행 컬렉션을 사용할 수 있습니다. 이 컬렉션은 내부적으로 락을 사용하지 않으면서도 안전하게 병행 접근이 가능합니다.

val queue = ConcurrentLinkedQueue<String>()

// 큐에 요소 추가
queue.add("example")
// 큐에서 요소 제거
queue.remove("example")

 

Android OS 7, 7.1 에서 CopyOnWriteArrayList 에서 sortyWith시 UnsupportedOperationException 에러 발생

Collections.java

위의 함수를 보면 안드로이드 타겟 버전 26이상 부터 sort가 되고,
25이하에서는 for문으로 set을 하는데 그 과정에서 UnsupportedOperationException을 발생 시킴

CopyOnWriteArrayList.java

 

찾아보니

add() 또는 remove()와 같은 수정 메서드를 사용하는 경우 CopyOnWriteArrayList 의 전체 내용이 새 내부 복사본에 복사된다.

이 간단한 사실로 인해 동시 수정이 발생하는 경우에도 안전한 방식으로 목록을 반복할 수 있다.

CopyOnWriteArrayList에서 iterator() 메서드를 호출할 때 CopyOnWriteArrayList 콘텐츠의 변경 불가능한 스냅샷으로 백업된 Iterator를 다시 가져온다.

iterator() 하면서 변경을 하려고 해서 오류가 발생한것으로 보인다.

 

참조 : 
https://dejavuhyo.github.io/posts/java-copyonwritearraylist/

반응형