본문 바로가기
카테고리 없음

Queue vs ConcurrentQueue

by 공부봇 2025. 11. 14.
반응형

둘 다 “큐”이긴 한데, 쓰레드 안전성이 가장 큰 차이입니다.


1. 네임스페이스 / 기본 성격

  • Queue<T>
    • System.Collections.Generic
    • 단일 쓰레드용 일반 큐
    • Enqueue/Dequeue 시에 별도 동기화 없음
  • ConcurrentQueue<T>
    • System.Collections.Concurrent
    • 멀티쓰레드 환경에서 사용하도록 설계된 락-프리(또는 최소 락) 큐
    • 여러 쓰레드가 동시에 Enqueue / Dequeue 해도 안전하게 동작

2. 쓰레드 안전성

  • Queue<T>
    • 여러 쓰레드에서 동시에 접근하면
      • 데이터 꼬임
      • 예외 발생 (InvalidOperationException 등)
      • 프로그램 비정상 동작 가능
    • 멀티쓰레드에서 쓰려면 직접 lock 걸어줘야
    • private readonly object _lock = new object(); private readonly Queue<int> _queue = new Queue<int>(); void Producer(int value) { lock (_lock) { _queue.Enqueue(value); } } bool TryConsume(out int value) { lock (_lock) { if (_queue.Count > 0) { value = _queue.Dequeue(); return true; } } value = default(int); return false; }
  • ConcurrentQueue<T>
    • 내부에서 이미 쓰레드 안전하게 동기화 처리
    • 여러 쓰레드가 동시에 Enqueue / TryDequeue 해도 무방
    • 보통 아래처럼 바로 사용
    • private readonly ConcurrentQueue<int> _queue = new ConcurrentQueue<int>(); void Producer(int value) { _queue.Enqueue(value); } bool TryConsume(out int value) { return _queue.TryDequeue(out value); }

3. 메서드 차이

  • Queue<T>
    • Enqueue(T item)
    • T Dequeue() (비어 있으면 예외)
    • T Peek() (비어 있으면 예외)
    • int Count { get; }
  • ConcurrentQueue<T>
    • Enqueue(T item)
    • bool TryDequeue(out T result) (비어 있으면 false 반환)
    • bool TryPeek(out T result)
    • int Count { get; }
      (멀티쓰레드 환경에서는 “정확한 순간값” 보장까진 아님, 참고용)

예외 대신 bool 리턴 + out 파라미터 패턴을 쓰는 게 특징입니다.


4. 성능 / 용도

  • Queue<T>
    • 싱글 쓰레드, 또는 lock을 직접 관리할 때 사용
    • 멀티쓰레드 고려 없어도 되니 가볍고 단순
  • ConcurrentQueue<T>
    • 멀티 프로듀서 / 멀티 컨슈머 패턴에서 사용
    • lock 최소화/없애도록 설계된 구조라, 다중 쓰레드에서 직접 lock 걸고 Queue<T> 쓰는 것보다 유리한 경우가 많음
    • 대신 구조가 복잡하고, Count 등의 연산은 “근사값” 개념으로 보는 게 맞음

5. 언제 뭘 쓰면 되는가

  • 단일 쓰레드 또는 큐 접근을 항상 한 쓰레드에서만 하는 경우
    • → Queue<T>로 충분
  • 여러 쓰레드에서 동시에 Enqueue/Dequeue 하는 경우 (예: Producer/Consumer 작업큐, 로그 큐 등)
    • → ConcurrentQueue<T>를 사용하는 것이 안전하고 편함

정리하면:

단일 쓰레드 / 직접 lock 관리 = Queue<T>
멀티쓰레드에서 동시에 사용 = ConcurrentQueue<T>

이렇게 생각하시면 됩니다.

반응형