본문 바로가기
UNITY/C#

[C#] ConcurrentDictionary :: 멀티스레드 환경을 위한 Dictionary

by 램플릿 2025. 7. 7.
ConcurrentDictionary

ConcurrentDictionary는 .NET (C#)에서 멀티스레드 환경에서 안전하게 데이터를 읽고 쓸 수 있도록 설계된 스레드 안전한 딕셔너리(Dictionary)입니다.

기본적으로 Dictionary<TKey, TValue>는 단일 스레드 환경에서는 매우 빠르지만, 멀티스레드 환경에서는 동기화 처리가 필요합니다. 이를 수동으로 처리하는 대신, ConcurrentDictionary<TKey, TValue>를 사용하면 .NET이 내부적으로 락(lock)과 분할(lock striping) 기술을 통해 성능과 안전성을 보장합니다.


✅ 주요 특징

 

스레드 안전(Thread-safe) 동시에 여러 스레드가 읽고/쓰기 가능
락 분할(Lock Striping) 전체 딕셔너리에 락을 걸지 않고, 키 범위에 따라 분할하여 효율성 확보
성능 최적화 다중 코어 환경에서도 높은 처리 성능
Atomic 연산 지원 AddOrUpdate, GetOrAdd 같은 연산이 원자적으로 수행됨

📦 네임스페이스 및 기본 구조

using System.Collections.Concurrent;

var dict = new ConcurrentDictionary<string, int>();

🛠️ 주요 메서드

TryAdd(key, value)

키가 존재하지 않을 때만 추가

bool added = dict.TryAdd("apple", 1);

 

TryGetValue(key, out value)

키가 있을 경우 값을 가져옴

if (dict.TryGetValue("apple", out int count))
{
    Console.WriteLine(count);
}

 

TryUpdate(key, newValue, comparisonValue)

값이 예상한 값일 경우에만 업데이트

bool updated = dict.TryUpdate("apple", 5, 1); // apple 값이 1이면 5로 변경

 

AddOrUpdate(key, addValue, updateFunc)

존재하지 않으면 추가, 있으면 업데이트

int result = dict.AddOrUpdate("banana", 1, (key, oldValue) => oldValue + 1);

 

GetOrAdd(key, valueFactory)

존재하지 않으면 추가, 있으면 기존 값 반환

int val = dict.GetOrAdd("cherry", key => 10);

🧠 내부 동작

  • 내부적으로 여러 개의 버킷(bucket)으로 나누고, 각 버킷마다 락을 걸어 동시 접근을 처리
  • 일반 lock을 사용하는 것보다 훨씬 성능이 좋음
  • foreach 사용 가능하지만, 컬렉션이 변할 수 있으므로 완전한 스냅샷이 아님

⚠️ 주의사항

  1. 순서 보장 없음 – 일반 Dictionary와 달리 순서를 보장하지 않음
  2. foreach 중 수정 가능 – 다른 스레드가 값을 추가/삭제할 수 있음 (예외 없음)
  3. Value 타입은 불변(immutable) 또는 안전하게 처리 필요 – 예: List 등 mutable 객체는 주의

🎯 언제 사용하나요?

  • 다중 스레드 환경에서 공통 딕셔너리를 접근해야 할 때
  • lock 사용 없이 간편하게 병렬 처리를 하고 싶을 때
  • Task/ThreadPool 기반의 비동기 코드에서 공유 데이터를 다룰 때

🔚 결론

ConcurrentDictionary는 멀티스레드 환경에서 안전하게 사용 가능한 Dictionary입니다. 락 없이 성능 저하를 최소화하면서도 안전한 자료구조를 필요로 할 때 매우 유용합니다.

'UNITY > C#' 카테고리의 다른 글

[C#] /// 주석(XML 주석)의 역할  (0) 2025.05.31
리스트와 딕셔너리  (0) 2024.11.22
=> 연산자 (람다 표현식)  (0) 2024.10.21
C# interface :: 'IEnumerator'와 'IEnumerable' (자료👀)  (0) 2024.06.25
C# Statements :: using, yield  (0) 2024.06.24