동기화 기본 형식 개요

.NET은 공유 리소스에 대한 액세스를 동기화하거나 스레드 상호 작용을 조정하는 데 사용할 수 있는 다양한 형식을 제공합니다.

중요

동일한 동기화 기본 형식 인스턴스를 사용하여 공유 리소스에 대한 액세스를 보호합니다. 다른 동기화 기본 형식 인스턴스를 사용하여 동일한 리소스를 보호하는 경우 동기화 기본 형식에서 제공하는 보호를 사용할 수 없게 됩니다.

WaitHandle 클래스 및 간단한 동기화 형식

여러 .NET 동기화 기본 형식이 System.Threading.WaitHandle 클래스에서 파생됩니다. 이 클래스는 네이티브 운영 체제 동기화 핸들을 캡슐화하고 스레드 상호 작용의 신호 메커니즘을 사용합니다. 해당 클래스에는 다음이 포함됩니다.

  • System.Threading.Mutex - 공유 리소스에 대한 배타적 액세스 권한을 부여합니다. 뮤텍스의 상태는 스레드가 소유하지 않는 경우 신호를 받습니다.
  • System.Threading.Semaphore - 공유 리소스 또는 리소스 풀에 동시에 액세스할 수 있는 스레드 수를 제한합니다. 세마포 상태는 해당 개수가 0보다 크면 신호 알림으로 설정되고 해당 개수가 0이면 신호 알림 해제로 설정됩니다.
  • System.Threading.EventWaitHandle - 스레드 동기화 이벤트를 나타내고 신호 알림 또는 신호 알림 해제 상태일 수 있습니다.
  • System.Threading.AutoResetEvent - EventWaitHandle에서 파생되고 신호 알림을 받으면 단일 대기 스레드를 해제한 후 자동으로 신호 알림 해제 상태로 다시 설정됩니다.
  • System.Threading.ManualResetEvent - EventWaitHandle에서 파생되고 신호 알림을 받을 경우 Reset 메서드가 호출될 때까지 신호 알림 상태를 유지합니다.

.NET Framework에서 WaitHandleSystem.MarshalByRefObject에서 파생되므로 대기 핸들을 사용하여 애플리케이션 도메인 경계에 걸쳐 스레드 활동을 동기화할 수 있습니다.

.NET Framework, .NET Core, .NET 5 이상에서 관련 형식 중 일부는 운영 체제 전체에 표시되고 프로세스 간 동기화에 사용할 수 있는 명명된 시스템 동기화 핸들을 나타낼 수 있습니다.

자세한 내용은 WaitHandle API 참조를 참조하세요.

간단한 동기화 형식은 기본 운영 체제 핸들을 사용하지 않고 일반적으로 향상된 성능을 제공합니다. 그러나 프로세스 간 동기화에는 사용할 수 없습니다. 한 애플리케이션 내에서 이러한 형식의 스레드 동기화를 사용합니다.

이러한 형식 중 일부는 WaitHandle에서 파생된 형식의 대체 항목입니다. 예를 들어 SemaphoreSlimSemaphore의 간단한 대체 항목입니다.

공유 리소스에 대한 액세스 동기화

.NET은 여러 스레드가 공유 리소스에 대한 액세스를 제어할 수 있는 다양한 동기화 기본 형식을 제공합니다.

Monitor 클래스

System.Threading.Monitor 클래스는 리소스를 식별하는 개체에 대한 잠금을 획득하거나 해제하여 공유 리소스에 대한 상호 배타적 액세스 권한을 부여합니다. 잠금이 유지되는 동안 잠금을 보유하는 스레드는 잠금을 다시 획득하고 해제할 수 있습니다. 다른 스레드는 잠금을 획득할 수 없도록 차단되고 Monitor.Enter 메서드는 잠금이 해제될 때까지 대기합니다. Enter 메서드는 해제된 잠금을 획득합니다. 또한 Monitor.TryEnter 메서드를 사용하여 스레드가 잠금을 획득하려고 시도하는 시간을 지정할 수도 있습니다. Monitor 클래스에 스레드 선호도가 있으므로 잠금을 획득한 스레드는 Monitor.Exit 메서드를 호출하여 잠금을 해제해야 합니다.

Monitor.Wait, Monitor.PulseMonitor.PulseAll 메서드를 사용하여 동일한 개체에 대한 잠금을 획득하는 스레드의 상호 작용을 조정할 수 있습니다.

자세한 내용은 Monitor API 참조를 참조하세요.

참고

Monitor 클래스를 직접 사용하는 대신 C#의 lock 문 및 Visual Basic의 SyncLock 문을 사용하여 공유 리소스에 대한 액세스를 동기화합니다. 이러한 문은 획득한 잠금이 항상 해제되도록 EnterExit 메서드와 try…finally 블록을 사용하여 구현됩니다.

Mutex 클래스

Monitor와 같은 System.Threading.Mutex 클래스는 공유 리소스에 대한 배타적 액세스 권한을 부여합니다. Mutex.WaitOne 메서드 오버로드 중 하나를 사용하여 뮤텍스의 소유권을 요청합니다. Monitor와 마찬가지로 Mutex에는 스레드 선호도가 있고 뮤텍스를 획득한 스레드는 Mutex.ReleaseMutex 메서드를 호출하여 뮤텍스를 해제해야 합니다.

Monitor와 달리 Mutex 클래스는 프로세스 간 동기화에 사용할 수 있습니다. 이를 수행하려면 운영 체제 전체에 표시되는 명명된 뮤텍스를 사용합니다. 명명된 뮤텍스 인스턴스를 만들려면 이름을 지정하는 뮤텍스 생성자를 사용합니다. Mutex.OpenExisting 메서드를 호출하여 기존 명명된 시스템 뮤텍스를 열 수도 있습니다.

자세한 내용은 뮤텍스 문서 및 Mutex API 참조를 참조하세요.

SpinLock 구조체

Monitor와 같은 System.Threading.SpinLock 구조체는 잠금의 가용성에 따라 공유 리소스에 대한 배타적 액세스 권한을 부여합니다. SpinLock이 사용할 수 없는 잠금을 획득하려고 하면 잠금을 사용할 수 있을 때까지 루프에서 반복적으로 확인하면서 대기합니다.

회전 잠금을 사용하는 이점 및 결점에 대한 자세한 내용은 SpinLock 문서 및 SpinLock API 참조를 참조하세요.

ReaderWriterLockSlim 클래스

System.Threading.ReaderWriterLockSlim 클래스는 쓰기 위해 공유 리소스에 대한 배타적 액세스 권한을 부여하고, 읽기 위해 여러 스레드가 동시에 리소스에 액세스하도록 허용합니다. ReaderWriterLockSlim을 사용하여 스레드로부터 안전한 읽기 작업을 지원하지만 쓰기 작업을 수행할 배타적 액세스 권한이 필요한 공유 데이터 구조에 대한 액세스를 동기화할 수 있습니다. 스레드가 배타적 액세스를 요청하면(예: ReaderWriterLockSlim.EnterWriteLock 메서드 호출을 통해) 모든 기존 판독기가 잠금을 종료하고 작성기가 잠금을 시작 및 종료할 때까지 후속 판독기 및 작성기 요청이 차단됩니다.

자세한 내용은 ReaderWriterLockSlim API 참조를 참조하세요.

세마포 및 SemaphoreSlim 클래스

System.Threading.SemaphoreSystem.Threading.SemaphoreSlim 클래스는 공유 리소스 또는 리소스 풀에 동시에 액세스할 수 있는 스레드 수를 제한합니다. 리소스를 요청하는 추가적인 스레드는 스레드가 세마포를 해제할 때까지 대기합니다. 세마포에는 스레드 선호도가 없으므로 한 스레드가 세마포를 획득할 수 있고 또 다른 스레드가 해당 세마포를 해제할 수 있습니다.

SemaphoreSlimSemaphore의 간단한 대체 항목이고 단일 프로세스 경계 내의 동기화에만 사용할 수 있습니다.

Windows에서는 프로세스 간 동기화에 Semaphore를 사용할 수 있습니다. 이 작업을 수행하려면 이름을 지정하는 Semaphore세마포 생성자 중 하나 또는 메서드를 사용하여 명명된 시스템 세마포를 나타내는 Semaphore.OpenExisting 인스턴스를 만듭니다. SemaphoreSlim은 명명된 시스템 세마포를 지원하지 않습니다.

자세한 내용은 세마포 및 SemaphoreSlim 문서와 Semaphore 또는 SemaphoreSlim API 참조를 참조하세요.

스레드 상호 작용 또는 신호

스레드 상호 작용(또는 스레드 신호)은 스레드가 계속 진행하기 위해 하나 이상의 스레드에서 알림이나 신호를 기다려야 함을 의미합니다. 예를 들어 스레드 A가 스레드 B의 Thread.Join 메서드를 호출하는 경우 스레드 B가 완료될 때까지 스레드 A가 차단됩니다. 이전 섹션에 설명된 동기화 기본 형식은 신호를 위한 다른 메커니즘을 제공합니다. 잠금을 해제함으로써 스레드는 또 다른 스레드에 잠금을 획득하면 계속 진행할 수 있음을 알립니다.

이 섹션에서는 .NET에서 제공하는 추가 신호 구문을 설명합니다.

EventWaitHandle, AutoResetEvent, ManualResetEvent 및 ManualResetEventSlim 클래스

System.Threading.EventWaitHandle 클래스는 스레드 동기화 이벤트를 나타냅니다.

동기화 이벤트는 신호 알림 또는 신호 알림 해제 상태일 수 있습니다. 이벤트 상태가 신호 알림 해제인 경우 이벤트의 WaitOne 오버로드를 호출하는 스레드는 이벤트가 신호 알림을 받을 때까지 차단됩니다. EventWaitHandle.Set 메서드는 이벤트 상태를 신호 알림으로 설정합니다.

신호 알림을 받은 EventWaitHandle의 동작은 재설정 모드에 따라 다릅니다.

Windows에서는 프로세스 간 동기화에 EventWaitHandle를 사용할 수 있습니다. 이 작업을 수행하려면 이름을 지정하는 EventWaitHandleEventWaitHandle 생성자 중 하나 또는 메서드를 사용하여 명명된 시스템 동기화 이벤트를 나타내는 EventWaitHandle.OpenExisting 인스턴스를 만듭니다.

자세한 내용은 EventWaitHandle 문서를 참조하세요. API 참조에 대해서는 EventWaitHandle, AutoResetEvent, ManualResetEventManualResetEventSlim을 참조하세요.

CountdownEvent 클래스

System.Threading.CountdownEvent 클래스는 개수가 0일 때 설정되는 이벤트를 나타냅니다. CountdownEvent.CurrentCount는 0보다 크지만 CountdownEvent.Wait를 호출하는 스레드가 차단됩니다. CountdownEvent.Signal을 호출하여 이벤트의 수를 감소시킵니다.

한 스레드의 신호로 다중 스레드를 차단 해제하는 데 사용할 수 있는 ManualResetEvent 또는 ManualResetEventSlim와 달리, CountdownEvent를 사용하여 여러 스레드의 신호로 하나 이상의 스레드를 차단 해제할 수 있습니다.

자세한 내용은 CountdownEvent 문서 및 CountdownEvent API 참조를 참조하세요.

Barrier 클래스

System.Threading.Barrier 클래스는 스레드 실행 경계를 나타냅니다. Barrier.SignalAndWait 메서드를 호출하는 스레드는 장벽에 도달했다는 신호 알림을 보내고 다른 참가자 스레드가 경계에 도달할 때까지 대기합니다. 모든 참가자 스레드는 장벽에 도달하면 계속 진행하며 장벽이 다시 설정되고 다시 사용할 수 있습니다.

하나 이상의 스레드가 다음 계산 단계로 진행하기 전에 다른 스레드의 결과를 필요로 할 때 Barrier를 사용할 수 있습니다.

자세한 내용은 Barrier 문서 및 Barrier API 참조를 참조하세요.

Interlocked 클래스

System.Threading.Interlocked 클래스는 변수에서 단순 원자성 작업을 수행하는 정적 메서드를 제공합니다. 해당 원자성 작업에는 비교에 따른 추가, 증가 및 감소, 교환, 조건부 교환이 포함되고 64비트 정수 값을 읽는 작업이 포함됩니다.

자세한 내용은 Interlocked API 참조를 참조하세요.

SpinWait 구조체

System.Threading.SpinWait 구조체는 회전 기반 대기를 지원합니다. 이벤트가 신호를 받거나 조건이 충족될 때까지 스레드가 대기해야 하지만 대기 핸들을 사용하거나 현재 스레드를 차단하여 실제 대기 시간이 필요한 대기 시간보다 적을 것으로 예상할 때 이를 사용할 수 있습니다. SpinWait를 사용하면 대기하는 동안 스핀하고 지정된 시간 안에 조건이 충족되지 않을 경우에만 대기 또는 중지를 통해 양보하는 짧은 기간을 지정할 수 있습니다.

자세한 내용은 SpinWait 문서 및 SpinWait API 참조를 참조하세요.

참조