Wie wähle ich zwischen Semaphore und SemaphoreSlim?

108

Ihre öffentlichen Schnittstellen sehen ähnlich aus. In der Dokumentation heißt es, dass SemaphoreSlim eine einfache Alternative ist und keine Windows-Kernel-Semaphoren verwendet. Diese Ressource gibt an, dass das SemaphoreSlim viel schneller ist. In welchen Situationen ist das SemaphoreSlim gegenüber dem Semaphore sinnvoller und umgekehrt?

Michael Hedgpeth
quelle
1
Semaphore gibt den Job immer an das Betriebssystem weiter. Das macht es relativ teuer, wenn das Semaphor nicht stark umkämpft ist, der Kernel-Aufruf kostet leicht 400 Nanosekunden. Der schlanke Gefallen versucht zunächst, es mit einer gemeinsam genutzten Variablen billig zu machen, ruft nur dann das Betriebssystem auf, wenn dies nicht funktioniert hat. Sie mögen immer billig, außer in dem Eckfall, in dem das Semaphor von mehreren Prozessen gemeinsam genutzt werden muss.
Hans Passant

Antworten:

64

Ein Unterschied besteht darin, dass SemaphoreSlimkeine benannten Semaphoren zulässig sind, die systemweit sein können. Dies würde bedeuten, dass ein SemaphoreSlim nicht für die prozessübergreifende Synchronisation verwendet werden kann.

In der MSDN-Dokumentation wird auch angegeben, dass SemSlim verwendet werden sollte, wenn "Wartezeiten voraussichtlich sehr kurz sind". Das passt normalerweise gut zu der Idee, dass die schlanke Version für die meisten Kompromisse leichter ist.

Andrew Barber
quelle
66
Ich wünschte, MS hätte etwas darüber geschrieben, was passiert, wenn die Wartezeiten nicht "sehr kurz" sind.
John Reynolds
79
... oder was "sehr kurz" bedeutet
Richard Szalay
9
Je nach System 1 Mikrosekunde für Semaphore und 1/4 Mikrosekunde für SemaphoreSlim, um eine WaitOne durchzuführen oder ["C # 5.0 in a Nutshell" freizugeben. 890] Vielleicht meinen sie das mit sehr kurzen Wartezeiten?
David Sherret
2
@dhsto Gute Referenz! Aber ich vermute, der verlinkte Artikel bedeutet "wenn die Wartezeiten für den Zugriff auf die gemeinsam genutzte Ressource sehr kurz sind" - dh die Ressource wird nicht für lange Zeiträume exklusiv verwendet - anstatt die Wartezeiten für den Semaphorcode selbst zu bedeuten? Der Semaphorcode wird immer ausgeführt, unabhängig davon, wie lange die Ressource gesperrt bleibt.
Culix
4
@culix Wenn ich mir die Quelle für Semaphore versus SemaphoreSlim anschaue, vermute ich, dass der Hauptgrund dafür, dass SemaphoreSlim nur für "sehr kurze" Wartezeiten verwendet werden sollte, darin besteht, dass eine Drehwartezeit verwendet wird. Dies ist reaktionsschneller, verbraucht jedoch viel CPU und wäre für längere Wartezeiten, in denen sofortige Antworten weniger wichtig sind, verschwenderisch. Semaphor blockiert stattdessen den Thread.
R2_118
17

Die MSDN-Dokumentation beschreibt den Unterschied.

In einem Satz:

  • Die SemaphoreSlim-Klasse stellt ein leichtes, schnelles Semaphor dar, das zum Warten innerhalb eines einzelnen Prozesses verwendet werden kann, wenn die Wartezeiten voraussichtlich sehr kurz sind.
Joe
quelle
1
Verwenden Sie dazu SemaphoreSlim in allen Fällen, in denen Ihre Anwendung der einzige Prozess auf Ihrem Computer ist, der auf dieses Semaphor zugreifen muss.
Austin Salgat
2
@Salgat Warum würdest du das tun? Wie in anderen Antworten beschrieben, SemaphoreSlimwird es mit SpinWait implementiert. Wenn Sie also viel darauf warten, verschwenden Sie viel CPU-Zeit. Was nicht einmal eine gute Idee ist, wenn Ihr Prozess der einzige Prozess auf dem Computer ist.
M. Stramm
In der MSDN-Dokumentation heißt es: "Die SemaphoreSlim-Klasse ist das empfohlene Semaphor für die Synchronisierung innerhalb einer einzelnen App." Mit Ausnahme von Sonderfällen sollten Sie standardmäßig SemaphoreSlim verwenden, wenn nur ein Prozess dieses Semaphor verwendet. Spezielle Ausnahmen bestehen im Allgemeinen für jeden gleichzeitigen Datentyp, was selbstverständlich ist.
Austin Salgat
17

SemaphoreSlim basiert auf SpinWait und Monitor, sodass der Thread, der darauf wartet, die Sperre zu erhalten, einige Zeit CPU-Zyklen brennt, in der Hoffnung, die Sperre zu erhalten, bevor er einem anderen Thread nachgibt. Wenn dies nicht der Fall ist, können die Systeme mithilfe des Threads den Kontext wechseln und versuchen es erneut (durch Brennen einiger CPU-Zyklen), sobald das Betriebssystem diesen Thread erneut plant. Bei langen Wartezeiten kann dieses Muster eine erhebliche Anzahl von CPU-Zyklen durchbrennen. Das beste Szenario für eine solche Implementierung ist also, wenn die meiste Zeit keine Wartezeit besteht und Sie die Sperre fast sofort erhalten können.

Semaphore basiert auf der Implementierung im Betriebssystemkern. Jedes Mal, wenn Sie die Sperre erwerben, verbringen Sie eine Menge CPU-Zyklen, aber danach schläft der Thread einfach so lange wie nötig, um die Sperre zu erhalten.

Dmytro Zakharov
quelle
12

In Bezug auf "kurze Zeiten" Kontroverse:

Zumindest die MSDN-Dokumentation von SemaphoreSlim besagt dies

Die SemaphoreSlim-Klasse ist das empfohlene Semaphor für die Synchronisation innerhalb einer einzelnen App.

im Abschnitt Bemerkungen. Im selben Abschnitt wird auch der Hauptunterschied zwischen Semaphore und SemaphoreSlim erläutert:

Das SemaphoreSlim ist eine einfache Alternative zur Semaphore-Klasse, die keine Windows-Kernel-Semaphoren verwendet. Im Gegensatz zur Semaphore-Klasse unterstützt die SemaphoreSlim-Klasse keine benannten Systemsemaphoren. Sie können es nur als lokales Semaphor verwenden.

Shaedar
quelle
1
Weitere Informationen: [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

Ich habe mir hier den Quellcode angesehen und mir Folgendes ausgedacht:

  1. Sowohl Semaphore als auch SemaphoreSlim stammen von WaitHandle, das intern das native Win32-Handle verwendet. Aus diesem Grund müssen Sie beide entsorgen (). Die Vorstellung, dass Slim leicht ist, ist also verdächtig.

  2. SemaphoreSlim verwendet SpinWait intern, Semaphore jedoch nicht. Das sagt mir, dass Semaphore in Fällen, in denen eine lange Wartezeit erwartet wird, zumindest in dem Sinne besser abschneiden sollte, dass es Ihre CPU nicht erstickt.

ILIA BROUDNO
quelle
2
SemaphoreSlim ist nicht von WaitHandle abgeleitet. Tatsächlich wurde es mit einem einzigen Ziel erstellt - das Ableiten von WaitHandle, einem Kernel-Space-Primitiv, bei Aufgaben zu eliminieren, bei denen Sie Vorgänge innerhalb nur eines Prozesses synchronisieren müssen.
Igor V Savchenko