Semaphore와 SemaphoreSlim 중에서 어떻게 선택합니까?


109

그들의 공용 인터페이스는 비슷하게 보입니다. 문서 SemaphoreSlim 경량 대안 및 Windows 커널 세마포어를 사용하지 않는 상태. 이 리소스 는 SemaphoreSlim이 훨씬 빠르다는 것을 나타냅니다. 어떤 상황에서 SemaphoreSlim이 Semaphore보다 더 합리적이고 그 반대의 경우도 마찬가지입니까?


1
Semaphore는 항상 작업을 OS로 전달합니다. 세마포어가 강하게 경쟁하지 않으면 상대적으로 비용이 많이 들고 커널 호출에 400 나노초가 소요됩니다. 빈약 한 호의는 먼저 공유 변수를 사용하여 저렴하게 수행하려고 시도하지만 작동하지 않을 때만 OS를 호출합니다. 세마포어를 여러 프로세스에서 공유해야하는 경우를 제외하고는 항상 저렴한 것을 좋아합니다.
Hans Passant

답변:


64

한 가지 차이점은 SemaphoreSlim시스템 전체 일 수있는 명명 된 세마포어를 허용하지 않는다는 것입니다. 이는 SemaphoreSlim을 프로세스 간 동기화에 사용할 수 없음을 의미합니다.

MSDN 설명서 에는 "대기 시간이 매우 짧을 것으로 예상되는"경우 SemSlim을 사용해야한다고 나와 있습니다. 그것은 일반적으로 슬림 버전이 대부분의 트레이드 오프에 대해 더 가볍다는 생각과 잘 어울립니다.


66
나는 MS가 대기 시간이 "매우 짧지"않을 때 일어나는 일에 대해 뭔가를 작성했으면한다.
John Reynolds 2012 년

79
... 또는 무엇을 "매우 짧은"수단
리처드 Szalay

9
시스템에 따라 Semaphore의 경우 1 마이크로 초, SemaphoreSlim이 WaitOne 또는 릴리스를 수행하는 경우 1/4 마이크로 초 [ "C # 5.0 in a Nutshell"pg. 890] 그래서 그것이 그들이 매우 짧은 대기 시간을 의미하는 것일까 요?
David Sherret

2
@dhsto 좋은 참조! 그러나 링크 된 기사가 "공유 리소스에 액세스하는 데 걸리는 대기 시간이 매우 짧을 때"를 의미한다고 생각합니다. 즉, 리소스가 세마포어 코드 자체에 대한 대기 시간을 의미하는 것이 아니라 오랜 시간 동안 독점적으로 사용되지 않습니다. 세마포어 코드는 리소스가 잠긴 기간에 관계없이 항상 실행됩니다.
culix

4
@culix Semaphore 대 SemaphoreSlim의 소스를 살펴보면 SemaphoreSlim이 "매우 짧은"대기에만 사용해야하는 주된 이유는 스핀 대기를 사용하기 때문이라고 생각합니다. 이것은 응답 성이 더 높지만 CPU를 많이 소모하고 즉각적인 응답이 덜 중요한 긴 대기 시간 동안 낭비됩니다. Semaphore는 대신 스레드를 차단합니다.
r2_118

17

MSDN 문서 에 차이점이 설명되어 있습니다.

한 문장으로 :

  • SemaphoreSlim 클래스는 대기 시간이 매우 짧을 것으로 예상되는 단일 프로세스 내에서 대기하는 데 사용할 수있는 가볍고 빠른 세마포어를 나타냅니다.

1
여기에 추가하려면 응용 프로그램이 해당 Semaphore에 액세스해야하는 컴퓨터의 유일한 프로세스 인 모든 경우에 SemaphoreSlim을 사용하십시오.
Austin Salgat

2
@Salgat 왜 그렇게 하시겠습니까? 다른 답변에서 설명했듯이 SemaphoreSlimSpinWait을 사용하여 구현되므로 많이 기다리면 많은 CPU 시간을 낭비하게됩니다. 당신의 프로세스가 컴퓨터의 유일한 프로세스라면 좋은 생각조차 아닙니다.
M.Stramm

MSDN 문서에서 "SemaphoreSlim 클래스는 단일 앱 내 동기화를위한 권장 세마포입니다." 특별한 경우를 제외하고 하나의 프로세스 만 해당 세마포어를 사용하는 경우 SemaphoreSlim을 사용하도록 기본 설정해야합니다. 일반적으로 동시 데이터 유형에는 특별한 예외가 존재합니다.
Austin Salgat 2016

17

SemaphoreSlim은 SpinWait 및 Monitor를 기반으로하므로 잠금을 획득하기 위해 대기하는 스레드는 다른 스레드에 양보하기 전에 잠금을 획득하기 위해 일정 시간 동안 CPU주기를 굽습니다. 그렇지 않은 경우 스레드는 OS가 해당 스레드를 다시 예약하면 시스템이 컨텍스트를 전환하고 (일부 CPU주기를 태워서) 다시 시도 할 수 있도록합니다. 오래 기다리면이 패턴은 상당한 양의 CPU주기를 소모 할 수 있습니다. 따라서 이러한 구현을위한 최상의 시나리오는 대부분의 경우 대기 시간이없고 거의 즉시 잠금을 획득 할 수있는 경우입니다.

Semaphore는 OS 커널의 구현에 의존하므로 잠금을 획득 할 때마다 상당한 CPU주기를 소비하지만 그 후에는 스레드가 잠금을 획득하는 데 필요한만큼 잠자기 만합니다.


12

"단기"논란에 관하여 :

최소한 SemaphoreSlim MSDN 문서 에는

SemaphoreSlim 클래스는 단일 앱 내 동기화에 권장되는 세마포어입니다.

비고 섹션에서. 같은 섹션에서는 Semaphore와 SemaphoreSlim의 주요 차이점도 설명합니다.

SemaphoreSlim은 Windows 커널 세마포를 사용하지 않는 Semaphore 클래스에 대한 경량 대안입니다. Semaphore 클래스와 달리 SemaphoreSlim 클래스는 명명 된 시스템 세마포를 지원하지 않습니다. 로컬 세마포로만 사용할 수 있습니다.


1
자세한 내용 : [SemaphoreSlim and other locks] use busy spinning for brief periods before they put the thread into a true Wait state. When wait times are expected to be very short, spinning is far less computationally expensive than waiting, which involves an expensive kernel transition: dotnet.github.io/docs/essentials/collections/…
Marco Sulla

0

여기 에서 소스 코드를 살펴 보았는데 이것이 제가 생각 해낸 것입니다.

  1. Semaphore와 SemaphoreSlim은 모두 내부적으로 Win32 네이티브 핸들을 사용하는 WaitHandle에서 파생됩니다. 그래서 둘 다 Dispose ()해야합니다. 따라서 Slim이 가볍다는 생각은 의심 스럽다.

  2. SemaphoreSlim은 내부적으로 SpinWait를 사용하지만 Semaphore는 사용하지 않습니다. 즉, 대기 시간이 길 것으로 예상되는 경우 Semaphore가 CPU를 질식시키지 않는다는 점에서 적어도 더 나은 성능을 발휘해야합니다.


2
SemaphoreSlim은 WaitHandle에서 파생되지 않습니다. 실제로 이것은 하나의 프로세스 내에서만 작업을 동기화해야하는 작업에서 커널 공간 원시인 WaitHandle에서 파생되는 것을 제거하는 단일 목표로 만들어졌습니다.
Igor V Savchenko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.