멀티스레드 환경에서 ArrayList를 안전하게 사용하려면 동기화 처리가 필수입니다. C#에서는 ArrayList.Synchronized 메서드를 사용하여 간단하게 스레드로부터 안전한(thread-safe) 래퍼(wrapper)를 만들 수 있습니다.
SyncRoot 속성으로 컬렉션 잠그기
컬렉션을 직접 순회할 때는 SyncRoot 속성을 이용해 잠금(lock)을 걸어야 합니다. 다음은 foreach문 반복 중 컬렉션이 다른 스레드에 의해 변경되지 않도록 보호하는 예제입니다.
ArrayList arr = new ArrayList();
lock(arr.SyncRoot) {
foreach (object ele in arr) {
}
}
ArrayList 동기화 상태 확인하기
아래 전체 예제는 Synchronized 메서드로 생성한 래퍼와 원본 ArrayList의 동기화 여부를 IsSynchronized 속성으로 확인하는 코드입니다.
예제 코드
using System;
using System.Collections;
public class Demo {
public static void Main() {
ArrayList arr1 = new ArrayList();
arr1.Add("One");
arr1.Add("Two");
arr1.Add("Three");
arr1.Add("Four");
arr1.Add("Five");
arr1.Add("Six");
arr1.Add("Seven");
arr1.Add("Eight");
// ArrayList에 동기화된 래퍼 설정
ArrayList arr2 = ArrayList.Synchronized(arr1);
// 첫 번째 ArrayList의 동기화 상태 출력
Console.WriteLine("arr1 = {0}", arr1.IsSynchronized ? " synchronized" : "not synchronized");
// 두 번째 ArrayList의 동기화 상태 출력
Console.WriteLine("arr2 = {0}", arr2.IsSynchronized ? "synchronized" : "not synchronized");
}
}
실행 결과
arr1 = not synchronized
arr2 = synchronized
핵심 정리
- 원본 ArrayList(arr1)는 기본적으로 동기화되어 있지 않습니다.
- ArrayList.Synchronized() 메서드는 기존 컬렉션을 감싸는 동기화된 래퍼를 반환합니다.
- IsSynchronized 속성으로 해당 컬렉션이 스레드로부터 안전한지 확인할 수 있습니다.
- 동기화된 래퍼라도 열거(enumeration) 작업 시에는
SyncRoot로 명시적인 잠금이 필요합니다.