Semaphore
Semaphore 는 나이트클럽에 빗대어 묘사할 수 있습니다: 정원이 정해져 있으며, 경비원에 의해 관리됩니다. 정원이 차면 더 이상 사람들이 입장할 수 없으며, 바깥에 대기열이 생깁니다. 한 사람이 나갈 때마다 대기열의 앞에서 한 사람씩 들어옵니다. 생성자는 최소한 두 개의 인수를 필요로 합니다 : 현재 나이트클럽에 들어갈 수 있는 자리 수와 클럽의 총 정원 수입니다.
정원이 1 인 Semaphore 는 Mutex 나 lock 과 유사하지만, Semaphore 는 특정 Thread 의 소유 개념이 없습니다. Semaphore 에서 Release 를 호출할 수 있는 Thread 는 어느 것이든 상관없지만, Mutex 와 lock 에서는 잠금 상태로 전환된 Thread 만이 이를 해제할 수 있습니다.
이 클래스에는 기능적으로 유사한 두 가지 버전이 있습니다 : Semaphore 와 SemaphoreSlim입니다. 후자는 .NET Framework 4.0 에서 도입되었으며, Parallel Programming (병렬 프로그래밍) 의 저지연 요구를 충족하도록 최적화되었습니다. 또한 전통적인 멀티스레딩에서도 유용하며, 대기 중에 취소 토큰을 지정할 수 있습니다. 하지만 프로세스 간의 신호로는 사용할 수 없습니다.
Semaphore 는 WaitOne 또는 Release 호출 시 약 1 μs (마이크로초) 를 소요하며, SemaphoreSlim은 그보다 약 1 / 4 정도의 시간을 소요합니다.
Semaphore 는 동시성 제한에 유용할 수 있으며, 너무 많은 Thread 들이 동시에 특정 코드를 실행하지 못하도록 할 수 있습니다. 다음 예시에서는 5 개의 스레드가 1 회당 3 개까지만 들어올 수 있는 나이트클럽에 들어가려고 한다고 가정해봅니다 :
class TheClub // 문단속 리스트 없음!
{
static SemaphoreSlim _sem = new SemaphoreSlim (3); // 정원은 3
static void Main()
{
for (int i = 1; i <= 5; i++) new Thread (Enter).Start (i);
}
static void Enter (object id)
{
// Threads 들 입장
Console.WriteLine (id + " wants to enter");
// 경비원 _sem 이 제한
_sem.Wait();
// 한 번에 세 개의 Threads 까지만 입장을 허용
Console.WriteLine (id + " is in!");
// 인원 수 * 1 초
Thread.Sleep (1000 * (int) id);
// Thread 는 클럽을 빠져나가고
Console.WriteLine (id + " is leaving");
// 다시 열어준다.
_sem.Release();
}
}
1 wants to enter
1 is in!
2 wants to enter
2 is in!
3 wants to enter
3 is in!
4 wants to enter
5 wants to enter
1 is leaving
4 is in!
2 is leaving
5 is in!
만약 Sleep 이 집약적인 디스크 I/O 를 수행하고 있다면, Semaphore 는 과도한 동시 하드 드라이브 활동을 제한하여 전체 성능을 향상시킬 수 있습니다.
이름이 있는 Semaphore 는 Mutex 와 같은 방식으로 프로세스 간을 넘나들 수 있습니다.
