Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# 스레드 안전 컬렉션 만들기 – System.Collections.Concurrent 완벽 가이드

C# 스레드 안전 컬렉션이란?

.NET Framework 4부터 System.Collections.Concurrent 네임스페이스가 공식적으로 도입되었습니다. 이 네임스페이스에는 스레드로부터 안전(thread-safe)하고 확장성(scalability)이 뛰어난 다양한 컬렉션 클래스들이 포함되어 있습니다.

이러한 컬렉션들은 한 번에 여러 스레드가 동시에 접근하고 조작할 수 있도록 설계되었기 때문에 동시성 컬렉션(Concurrent Collections)이라고 부릅니다. 일반적인 List<T>, Dictionary<TKey,TValue>를 멀티스레드 환경에서 직접 사용하면 데이터 손상이나 예외가 발생할 수 있지만, 동시성 컬렉션은 별도의 락 처리 없이도 안전하게 사용할 수 있다는 것이 가장 큰 장점입니다.

경량 동기화 메커니즘

동시성 컬렉션은 내부적으로 SpinLock, SpinWait와 같은 .NET Framework 4에서 새롭게 제공된 경량(lightweight) 동기화 메커니즘을 활용합니다. 무거운 lock 블록 대신 짧은 대기 시간을 효율적으로 처리하기 때문에 고성능 멀티스레딩 환경에서 오버헤드를 크게 줄일 수 있습니다.

주요 동시성 컬렉션 종류

C#에서 자주 사용되는 대표적인 동시성 컬렉션 타입은 다음과 같습니다.

타입설명
BlockingCollection<T>모든 타입에 대해 경계(bounding) 및 차단(blocking) 기능을 제공합니다.
ConcurrentDictionary<TKey,TValue>키-값 쌍으로 구성된 딕셔너리의 스레드 안전 구현체입니다.
ConcurrentQueue<T>FIFO(선입선출) 큐의 스레드 안전 구현체입니다.
ConcurrentStack<T>LIFO(후입선출) 스택의 스레드 안전 구현체입니다.
ConcurrentBag<T>순서가 없는 요소 집합의 스레드 안전 구현체입니다.
IProducerConsumerCollection<T>BlockingCollection에서 사용되기 위해 해당 타입이 반드시 구현해야 하는 인터페이스입니다.

ConcurrentStack<T> 사용 예제

ConcurrentStack<T>는 스레드로부터 안전한 후입선출(LIFO) 컬렉션입니다. Push 메서드로 요소를 추가하고, TryPop 또는 TryPeek 메서드로 요소를 꺼내거나 확인할 수 있습니다.

ConcurrentStack<int> cs = new ConcurrentStack<int>();
cs.Push(95);
cs.Push(120);
cs.Push(130);

위 코드는 여러 스레드가 동시에 접근하더라도 스택의 상태가 항상 일관성 있게 유지됩니다. 멀티스레드 환경에서 생산자-소비자 패턴이나 작업 큐를 구현할 때 동시성 컬렉션을 적극적으로 활용하면 코드의 안정성과 성능을 모두 향상시킬 수 있습니다.