이 글에서는 Java에서 발생하는 ConcurrentModificationException 에러와 그 해결 방법에 대해 설명합니다. 이 에러는 멀티스레드 환경에서 발생할 수 있는 공통적인 문제입니다. 이 글에서는 이 에러의 원인과 해결 방법을 자세히 알아보겠습니다.
문제상황:
다음은 실무에서 사용되는 코드 예시입니다. 여기에서는 멀티스레드 환경에서 List 객체를 수정하려고 할 때 발생하는 에러에 대해 살펴보겠습니다.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ConcurrentModificationExceptionExample {
public static void main(String[] args) {
List<String> dataList = new ArrayList<>();
dataList.add("Apple");
dataList.add("Banana");
dataList.add("Cherry");
// 첫 번째 스레드는 List를 순회하면서 데이터를 출력합니다.
Thread thread1 = new Thread(() -> {
for (String data : dataList) {
System.out.println("Thread1: " + data);
}
});
// 두 번째 스레드는 List에서 요소를 삭제합니다.
Thread thread2 = new Thread(() -> {
dataList.remove(1);
});
thread1.start();
thread2.start();
}
}
에러로그 내용:
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
at ConcurrentModificationExceptionExample.lambda$main$0(ConcurrentModificationExceptionExample.java:15)
at java.base/java.lang.Thread.run(Thread.java:829)
해결방법:
에러가 수정된 코드+ 수정된 부분에 대한 주석:
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
public class FixedConcurrentModificationExceptionExample {
public static void main(String[] args) {
// CopyOnWriteArrayList를 사용하여 동시 수정 문제를 해결합니다.
CopyOnWriteArrayList<String> dataList = new CopyOnWriteArrayList<>();
dataList.add("Apple");
dataList.add("Banana");
dataList.add("Cherry");
Thread thread1 = new Thread(() -> {
Iterator<String> iterator = dataList.iterator();
while (iterator.hasNext()) {
System.out.println("Thread1: " + iterator.next());
}
});
Thread thread2 = new Thread(() -> {
dataList.remove(1);
});
thread1.start();
thread2.start();
}
}
원인분석:
- 동시성: 동시성은 여러 개의 독립적인 작업을 동시에 처리하는 것을 의미합니다. 이를 효율적으로 처리하기 위해 자바에서는 멀티스레딩 기능을 제공합니다.
- 에러 발생 원인: 위의 예제에서는 두 개의 스레드가 동시에 ArrayList 객체에 접근하려고 합니다. 하나의 스레드가 List를 순회하면서 출력하고, 다른 스레드가 List의 요소를 삭제하려고 합니다. 이러한 동시 수정이 발생할 때 ArrayList는 동기화 메커니즘을 제공하지 않기 때문에 ConcurrentModificationException이 발생합니다.
- ConcurrentModificationException: 이 에러는 여러 스레드가 동시에 컬렉션을 수정하려고 할 때 발생합니다. ArrayList와 같은 컬렉션은 동기화를 제공하지 않아서, 여러 스레드가 동시에 수정 작업을 수행하면 예기치 않은 결과가 발생할 수 있습니다.
- 해결된 코드의 작동 원리: 이 문제를 해결하기 위해 CopyOnWriteArrayList를 사용했습니다. CopyOnWriteArrayList는 이름에서 알 수 있듯이, 동시 수정이 발생할 때 새로운 복사본을 만들어 이를 통해 동시 수정이 발생하는 상황을 해결합니다. 이 방식은 동시성을 보장하면서 원본 데이터 구조를 변경하지 않으므로 에러가 발생하지 않습니다.
참조 링크:
728x90