세마포 및 SemaphoreSlimSemaphore and SemaphoreSlim

로컬 또는 명명된(시스템 전체) 세마포를 나타내는 System.Threading.Semaphore 클래스는The System.Threading.Semaphore class represents a named (systemwide) or local semaphore. Win32 세마포 개체를 묶는 씬 래퍼입니다.It is a thin wrapper around the Win32 semaphore object. Win32 세마포는 리소스 풀에 대한 액세스를 제어하는 데 사용할 수 있는 가산 세마포입니다.Win32 semaphores are counting semaphores, which can be used to control access to a pool of resources.

SemaphoreSlim 클래스는 대기 시간이 매우 짧을 것으로 예상될 때 단일 프로세스 내에서 대기하는 데 사용할 수 있는 간단하고 빠른 세마포를 나타냅니다.The SemaphoreSlim class represents a lightweight, fast semaphore that can be used for waiting within a single process when wait times are expected to be very short. SemaphoreSlim은 CLR(공용 언어 런타임)에서 제공하는 동기화 기본 형식을 최대한 활용합니다.SemaphoreSlim relies as much as possible on synchronization primitives provided by the common language runtime (CLR). 그러나 필요에 따라 여러 세마포에 대해 대기를 지원할 수 있도록 지연 초기화된 커널 기반 대기 핸들도 제공합니다.However, it also provides lazily initialized, kernel-based wait handles as necessary to support waiting on multiple semaphores. 또한 SemaphoreSlim은 취소 토큰 사용도 지원하지만 명명된 세마포 또는 동기화용 대기 핸들 사용은 지원하지 않습니다.SemaphoreSlim also supports the use of cancellation tokens, but it does not support named semaphores or the use of a wait handle for synchronization.

제한된 리소스 관리Managing a Limited Resource

스레드는 WaitOne 메서드를 호출하여 세마포를 입력합니다. 이 메서드는 WaitHandle 개체의 경우 System.Threading.Semaphore 클래스에서 상속되고 SemaphoreSlim 개체의 경우에는 SemaphoreSlim.Wait 또는 SemaphoreSlim.WaitAsync 메서드에서 상속됩니다.Threads enter the semaphore by calling the WaitOne method, which is inherited from the WaitHandle class, in the case of a System.Threading.Semaphore object, or the SemaphoreSlim.Wait or SemaphoreSlim.WaitAsync method, in the case of a SemaphoreSlim object. 호출이 반환되면 세마포 수가 감소합니다.When the call returns, the count on the semaphore is decremented. 스레드가 항목을 요청할 때 개수가 0이면 해당 스레드는 차단됩니다.When a thread requests entry and the count is zero, the thread blocks. 스레드가 Semaphore.Release 또는 SemaphoreSlim.Release 메서드를 호출하여 세마포를 해제하면 차단된 스레드를 입력할 수 있게 됩니다.As threads release the semaphore by calling the Semaphore.Release or SemaphoreSlim.Release method, blocked threads are allowed to enter. FIFO(선입 선출) 또는 LIFO(후입 선출)와 같이 차단된 스레드가 세마포에 입력되는 보장된 순서는 없습니다.There is no guaranteed order, such as first-in, first-out (FIFO) or last-in, first-out (LIFO), for blocked threads to enter the semaphore.

스레드는 System.Threading.Semaphore 개체의 WaitOne 메서드 또는 SemaphoreSlim 개체의 Wait 메서드를 반복적으로 호출하여 세마포를 여러 번 입력할 수 있습니다.A thread can enter the semaphore multiple times by calling the System.Threading.Semaphore object's WaitOne method or the SemaphoreSlim object's Wait method repeatedly. 세마포를 해제하려는 경우 스레드는 Semaphore.Release() 또는 SemaphoreSlim.Release() 메서드 오버로드를 같은 횟수만큼 호출하거나 Semaphore.Release(Int32) 또는 SemaphoreSlim.Release(Int32) 메서드 오버로드를 호출하고 해제할 항목 수를 지정할 수 있습니다.To release the semaphore, the thread can either call the Semaphore.Release() or SemaphoreSlim.Release() method overload the same number of times, or call the Semaphore.Release(Int32) or SemaphoreSlim.Release(Int32) method overload and specify the number of entries to be released.

세마포 및 스레드 IDSemaphores and Thread Identity

두 세마포 형식은 WaitOne, Wait, ReleaseSemaphoreSlim.Release 메서드 호출에 대해 스레드 ID를 적용하지 않습니다.The two semaphore types do not enforce thread identity on calls to the WaitOne, Wait, Release, and SemaphoreSlim.Release methods. 예를 들어 세마포의 일반적인 사용 시나리오에서는 생산자 스레드와 소비자 스레드가 사용되는데, 여기서 스레드 하나는 항상 세마포 수를 증가시키고 다른 하나는 항상 세마포 수를 감소시킵니다.For example, a common usage scenario for semaphores involves a producer thread and a consumer thread, with one thread always incrementing the semaphore count and the other always decrementing it.

프로그래머는 스레드가 세마포를 너무 여러 번 해제하지 않는지 확인해야 합니다.It is the programmer's responsibility to ensure that a thread does not release the semaphore too many times. 예를 들어 세마포의 최대 개수가 2개인데 스레드 A와 스레드 B가 모두 세마포를 입력한다고 가정해 보겠습니다.For example, suppose a semaphore has a maximum count of two, and that thread A and thread B both enter the semaphore. 스레드 B에서 프로그래밍 오류가 발생하여 Release가 두 번 호출되면 두 호출은 모두 성공합니다.If a programming error in thread B causes it to call Release twice, both calls succeed. 그러면 세마포 개수가 다 차서 스레드 A가 Release를 호출하면 SemaphoreFullException이 throw됩니다.The count on the semaphore is full, and when thread A eventually calls Release, a SemaphoreFullException is thrown.

명명된 세마포Named Semaphores

Windows 운영 체제에서는 세마포에 이름을 지정할 수 있습니다.The Windows operating system allows semaphores to have names. 명명된 세마포는 시스템 전체에 사용됩니다.A named semaphore is system wide. 즉, 명명된 세마포는 작성되고 나면 모든 프로세스의 모든 프로세스에 표시됩니다.That is, once the named semaphore is created, it is visible to all threads in all processes. 따라서 명명된 세마포는 스레드뿐 아니라 프로세스의 활동을 동기화하는 데도 사용할 수 있습니다.Thus, named semaphore can be used to synchronize the activities of processes as well as threads.

이름을 지정하는 생성자 중 하나를 사용하여 명명된 시스템 세마포를 나타내는 Semaphore 개체를 만들 수 있습니다.You can create a Semaphore object that represents a named system semaphore by using one of the constructors that specifies a name.

참고

명명된 세마포는 시스템 전체 세마포이므로 같은 명명된 세마포를 나타내는 Semaphore 개체를 여러 개 사용할 수 있습니다.Because named semaphores are system wide, it is possible to have multiple Semaphore objects that represent the same named semaphore. 생성자 또는 Semaphore.OpenExisting 메서드를 호출할 때마다 새 Semaphore 개체가 만들어집니다.Each time you call a constructor or the Semaphore.OpenExisting method, a new Semaphore object is created. 같은 이름을 반복적으로 지정하면 같은 명명된 세마포를 나타내는 개체가 여러 개 만들어집니다.Specifying the same name repeatedly creates multiple objects that represent the same named semaphore.

명명된 세마포를 사용할 때는 주의해야 합니다.Be careful when you use named semaphores. 이러한 세마포는 시스템 전체 세마포이므로 같은 이름을 사용하는 다른 프로세스가 예기치 않게 세마포를 입력할 수 있습니다.Because they are system wide, another process that uses the same name can enter your semaphore unexpectedly. 그러면 동일 컴퓨터에서 실행되는 악성 코드가 이를 악용해 서비스 거부 공격을 수행할 수 있습니다.Malicious code executing on the same computer could use this as the basis of a denial-of-service attack.

명명된 세마포를 나타내는 Semaphore 개체를 보호하려면 액세스 제어 보안을 사용합니다. 이때 System.Security.AccessControl.SemaphoreSecurity 개체를 지정하는 생성자를 사용하는 것이 좋습니다.Use access control security to protect a Semaphore object that represents a named semaphore, preferably by using a constructor that specifies a System.Security.AccessControl.SemaphoreSecurity object. Semaphore.SetAccessControl 메서드를 사용하여 액세스 제어 보안을 적용할 수도 있지만 이렇게 하면 세마포 작성 시간과 보호가 적용되는 시간 사이에 취약한 기간이 생기게 됩니다.You can also apply access control security using the Semaphore.SetAccessControl method, but this leaves a window of vulnerability between the time the semaphore is created and the time it is protected. 액세스 제어 보안을 통해 세마포를 보호하면 악의적인 공격을 방지할 수는 있지만 의도하지 않은 이름 충돌 문제는 해결되지 않습니다.Protecting semaphores with access control security helps prevent malicious attacks, but does not solve the problem of unintentional name collisions.

참고 항목See also