C#에서 HybridDictionary는 컬렉션의 요소 수가 적을 때는 ListDictionary로, 요소 수가 많아지면 Hashtable로 자동 전환되는 컬렉션입니다. 멀티스레드 환경에서 여러 스레드가 동시에 같은 HybridDictionary에 접근할 때 데이터 무결성을 보장하려면 동기화(Synchronization) 처리가 필요합니다.
HybridDictionary에 대한 동기화 액세스를 얻는 핵심은 SyncRoot 속성과 lock 문입니다. SyncRoot 속성은 컬렉션에 대한 액세스를 동기화하는 데 사용할 수 있는 객체를 반환하며, 이 객체를 lock으로 감싸면 해당 블록 내에서 한 번에 하나의 스레드만 컬렉션에 접근할 수 있습니다.
예제 1: 두 개의 HybridDictionary 동기화 액세스
using System;
using System.Collections;
using System.Collections.Specialized;
public class Demo {
public static void Main() {
HybridDictionary dict1 = new HybridDictionary();
dict1.Add("A", "Books");
dict1.Add("B", "Electronics");
dict1.Add("C", "Smart Wearables");
dict1.Add("D", "Pet Supplies");
dict1.Add("E", "Clothing");
dict1.Add("F", "Footwear");
Console.WriteLine("HybridDictionary1 elements...");
foreach(DictionaryEntry d in dict1) {
Console.WriteLine(d.Key + " " + d.Value);
}
Console.WriteLine("Is the HybridDictionary1 having fixed size? = "+dict1.IsFixedSize);
Console.WriteLine("If HybridDictionary1 read-only? = "+dict1.IsReadOnly);
Console.WriteLine("Is HybridDictionary1 synchronized = "+dict1.IsSynchronized);
HybridDictionary dict2 = new HybridDictionary();
dict2.Add("1", "One");
dict2.Add("2", "Two");
dict2.Add("3", "Three");
dict2.Add("4", "Four");
dict2.Add("5", "Five");
dict2.Add("6", "Six");
Console.WriteLine("\nHybridDictionary2 elements...");
foreach(DictionaryEntry d in dict2) {
Console.WriteLine(d.Key + " " + d.Value);
}
Console.WriteLine("Is HybridDictionary1 equal to HybridDictionary2? = "+(dict1.Equals(dict2)));
Console.WriteLine("\nSynchronize access...");
lock(dict2.SyncRoot) {
foreach(DictionaryEntry d in dict2) {
Console.WriteLine(d.Key + " " + d.Value);
}
}
}
}출력 결과
위 코드를 실행하면 다음과 같은 출력이 생성됩니다.
HybridDictionary1 elements... A Books B Electronics C Smart Wearables D Pet Supplies E Clothing F Footwear Is the HybridDictionary1 having fixed size? = False If HybridDictionary1 read-only? = False Is HybridDictionary1 synchronized = False HybridDictionary2 elements... 1 One 2 Two 3 Three 4 Four 5 Five 6 Six Is HybridDictionary1 equal to HybridDictionary2? = False Synchronize access... 1 One 2 Two 3 Three 4 Four 5 Five 6 Six
코드 설명
- IsFixedSize: HybridDictionary가 고정 크기를 갖는지 여부를 나타내며, 위 예제에서는 False가 출력됩니다.
- IsReadOnly: 컬렉션이 읽기 전용인지 확인합니다. 이 역시 False입니다.
- IsSynchronized: 기본적으로 HybridDictionary는 스레드로부터 안전하지 않으므로 False를 반환합니다. 따라서 명시적인 동기화가 필요합니다.
- lock(dict2.SyncRoot): SyncRoot 객체를 잠금 대상으로 사용하여 열거 작업 중 다른 스레드가 컬렉션을 수정하지 못하도록 보장합니다.
예제 2: 단일 HybridDictionary 동기화 액세스
이번에는 하나의 HybridDictionary에 대해 동일한 방식으로 동기화 액세스를 적용해 보겠습니다.
using System;
using System.Collections;
using System.Collections.Specialized;
public class Demo {
public static void Main() {
HybridDictionary dict = new HybridDictionary();
dict.Add("A", "SUV");
dict.Add("B", "MUV");
dict.Add("C", "AUV");
Console.WriteLine("HybridDictionary elements...");
foreach(DictionaryEntry d in dict) {
Console.WriteLine(d.Key + " " + d.Value);
}
Console.WriteLine("\nSynchronize access...");
lock(dict.SyncRoot) {
foreach(DictionaryEntry d in dict) {
Console.WriteLine(d.Key + " " + d.Value);
}
}
}
}출력 결과
위 코드를 실행하면 다음과 같은 출력이 생성됩니다.
HybridDictionary elements... A SUV B MUV C AUV Synchronize access... A SUV B MUV C AUV
정리
HybridDictionary는 기본적으로 스레드로부터 안전하지 않으며, IsSynchronized 속성은 항상 False를 반환합니다. 멀티스레드 환경에서 안전하게 사용하려면 SyncRoot 속성을 lock 문으로 감싸 열거나 수정 작업을 동기화해야 합니다. 특히 foreach로 컬렉션을 순회하는 도중 다른 스레드가 요소를 추가하거나 삭제하면 InvalidOperationException이 발생할 수 있으므로, 열거 작업 시에는 반드시 lock 블록 내에서 수행하는 것이 좋습니다.