개발/자바
Collections : synchronized (list) {} 동기화 블록
피터JK
2025. 2. 20. 11:04
728x90
✅ 1. 동기화 블록의 필요성
자바의 Collections.synchronizedList() 메서드를 사용하면 동기화된 리스트를 만들 수 있습니다.
하지만, 반복문 (for-each, Iterator)을 사용할 때는 추가적인 동기화 블록이 필요합니다.
이유는 반복문 실행 중 리스트가 수정될 경우 ConcurrentModificationException이 발생할 가능성이 있기 때문입니다.
✅ 2. 코드 분석
synchronized (list) { // 🔹 리스트 전체에 대한 동기화 블록
for (String s : list) { // 🔹 리스트 요소를 순회
System.out.println(s);
}
}
✔ synchronized (list) {...}
- 리스트 전체에 대한 락(lock)을 걸어 여러 스레드에서 동시에 접근하는 것을 방지
- 이 블록 내부에서는 다른 스레드가 리스트를 수정할 수 없음
✔ for (String s : list) { ... }
- 동기화된 상태에서 리스트의 요소를 하나씩 가져와 출력
- 리스트가 수정되는 동안 반복문이 실행되면 예외(ConcurrentModificationException) 발생 가능하므로 동기화 필요
✅ 3. 예제 코드: 동기화 없이 발생하는 문제
synchronized 블록이 없을 때 여러 스레드가 리스트에 동시에 접근하면 예외 발생 가능
import java.util.*;
public class SynchronizedListExample {
public static void main(String[] args) {
List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("A");
list.add("B");
list.add("C");
// 새 스레드에서 리스트 수정
new Thread(() -> {
list.add("D");
list.remove("A");
}).start();
// 메인 스레드에서 리스트 순회 (동기화 안 하면 위험!)
for (String s : list) {
System.out.println(s); // 🔴 동기화하지 않으면 ConcurrentModificationException 발생 가능
}
}
}
✔ 출력 예시 (예외 발생 가능)
A
B
Exception in thread "main" java.util.ConcurrentModificationException
list를 반복문으로 읽는 도중, 다른 스레드가 수정하면 예외 발생
✅ 4. 해결 방법: 동기화 블록 추가
synchronized 블록을 사용하여 반복문 실행 중 다른 스레드가 접근하지 못하도록 보호
import java.util.*;
public class SynchronizedListExample {
public static void main(String[] args) {
List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("A");
list.add("B");
list.add("C");
new Thread(() -> {
synchronized (list) { // 🔹 리스트 수정 시 동기화
list.add("D");
list.remove("A");
}
}).start();
synchronized (list) { // 🔹 반복문 실행 시 동기화
for (String s : list) {
System.out.println(s);
}
}
}
}
✔ 출력 예시 (정상 실행, 예외 없음)
B
C
D
🔹 synchronized (list) {...} 블록을 사용하여 안전하게 동기화된 상태에서 리스트를 순회
✅ 5. 결론
- 동기화 리스트 (Collections.synchronizedList())를 사용해도 반복문 실행 중에는 추가적인 synchronized 블록이 필요
- 리스트를 읽는 동안 다른 스레드가 수정하면 ConcurrentModificationException 발생 가능
- 반복문 실행 시 synchronized (list) {...}로 동기화하면 안전하게 접근 가능
- 멀티스레드 환경에서 공유 리스트를 사용할 때는 항상 동기화 고려 필요
✔ synchronized (list) {} 블록은 멀티스레드 환경에서 컬렉션을 안전하게 사용할 때 필수!
728x90