ManualResetEvent와 ManualResetEventSlim

ManualResetEvent와 ManualResetEventSlim

ManualResetEventManualResetEventSlim은 .NET에서 스레드 동기화를 위해 사용되는 클래스입니다. 이 클래스들은 이벤트 기반 동기화 메커니즘으로, 한 스레드가 다른 스레드에 작업을 시작하거나 계속 진행할 수 있는 신호를 보낼 때 사용됩니다.

ManualResetEvent의 기본 동작

기본 개념

  • ManualResetEvent는 이벤트 객체를 생성하여 신호를 설정하거나 재설정Set/Reset할 수 있습니다.
  • 신호가 설정되면Set, 기다리고 있던 모든 스레드가 작업을 시작합니다.
  • 신호를 재설정Reset하면 다시 대기 상태로 돌아갑니다.

주요 메서드

  • Set(): 신호를 설정하여, 대기 중인 스레드들이 계속 실행되도록 합니다.
  • Reset(): 신호를 재설정하여, 이후의 스레드들이 대기 상태에 머물도록 합니다.
  • WaitOne(): 현재 스레드가 신호가 설정될 때까지 기다립니다.

구현 예

ManualResetEvent mre = new ManualResetEvent(false); // 초기 신호 상태: 비설정(false)
Task.Run(() =>
{
	Console.WriteLine("작업 중... 신호 대기 중");
	mre.WaitOne(); // 신호를 대기
	Console.WriteLine("신호 수신! 작업 재개");
});
Thread.Sleep(2000); // 2초 후 신호 전송
mre.Set(); // 신호 설정
// 작업 중... 신호 대기 중
// (2초 대기)
// 신호 수신! 작업 재개

특징

  • 신호가 설정되면 대기 중인 모든 스레드가 깨어납니다.
  • 신호는 수동으로 재설정Reset해야 다시 대기 상태로 돌아갑니다.

ManualResetEventSlim

기본 개념

  • ManualResetEventSlimManualResetEvent의 경량화된 버전입니다.
  • 내부적으로 스핀 대기spin-waiting를 사용하여, 잠깐 동안 신호를 기다릴 때 더 적은 리소스를 사용합니다.
  • 짧은 대기 시간에 적합합니다.

주요 차이점

특징ManualResetEventManualResetEventSlim
기본 사용커널 객체를 사용한 스레드 동기화사용자 모드에서 실행, 경량화된 동기화
스핀 대기(Spin-Waiting)없음짧은 시간 대기를 위해 스핀 대기 사용
성능대기 시간이 길거나 많은 스레드에 적합짧은 대기 시간 또는 적은 스레드에 적합
리소스 사용량더 많은 메모리와 CPU 사용더 적은 메모리와 CPU 사용
동기화 메커니즘커널 수준 신호 (Windows 이벤트 핸들)사용자 수준 신호
Wait 메서드의 타임아웃 지원지원지원

구현 예

ManualResetEventSlim mreSlim = new ManualResetEventSlim(false);
Task.Run(() =>
{
	Console.WriteLine("작업 중... 신호 대기 중");
	mreSlim.Wait(); // 신호를 대기
	Console.WriteLine("신호 수신! 작업 재개");
});
Thread.Sleep(2000); // 2초 후 신호 전송
mreSlim.Set(); // 신호 설정
// 작업 중... 신호 대기 중
// (2초 대기)
// 신호 수신! 작업 재개

특징

  • 스핀 대기를 사용하므로 짧은 대기 시간에서 효율적입니다.
  • ManualResetEvent보다 경량화되어 빠르고 적은 리소스를 사용합니다.

차이점 정리

특징ManualResetEventManualResetEventSlim
리소스 관리커널 리소스 사용사용자 모드에서 경량 구현
성능긴 대기 시간에 적합짧은 대기 시간에 적합
스핀 대기없음있음
Wait 성능커널 핸들 대기를 사용사용자 모드 대기로 빠르게 처리
동기화 객체의 크기더 많은 메모리와 CPU 사용더 작은 메모리 사용
추천 사용 사례여러 스레드가 긴 대기 시간을 가지는 경우적은 스레드와 짧은 대기 시간의 경우
타임아웃 설정가능가능
동기화 메커니즘커널 수준 신호 (Windows 이벤트 핸들)사용자 수준 신호

사용 사례

ManualResetEvent를 사용하는 경우

  • 여러 스레드가 긴 시간 동안 신호를 대기해야 하는 경우.
  • OS 커널 수준의 동기화가 필요한 경우.
  • 신뢰성과 정확도가 중요한 고부하 시스템.

ManualResetEventSlim을 사용하는 경우

  • 신호를 짧게 기다려야 하는 경우.
  • 리소스가 제한적이고 가벼운 동기화가 필요한 경우.
  • 사용자 수준에서 빠른 대기를 수행해야 하는 경우.

주의 사항

스핀 대기의 부작용

  • ManualResetEventSlim은 CPU 자원을 많이 소모할 수 있습니다. 짧은 대기에는 적합하지만 긴 대기에는 부적합합니다.

대기 시간이 길 경우

  • 대기 시간이 긴 경우에는 ManualResetEvent를 사용해 커널 수준의 대기 처리를 수행하는 것이 적합합니다.

Dispose 호출 필요

  • ManualResetEventManualResetEventSlim 모두 사용이 끝난 후 Dispose()를 호출해야 리소스 누수를 방지할 수 있습니다.