Semaphore und SemaphoreSlim
Die System.Threading.Semaphore-Klasse stellt ein benanntes (systemweites) oder lokales Semaphor dar. Es ist ein einfacher Wrapper um das Win32-Semaphorobjekt. Win32-Semaphoren sind zählende Semaphoren, die zur Steuerung des Zugriffs auf einen Ressourcenpool verwendet werden können.
Die SemaphoreSlim-Klasse stellt ein einfaches, schnelles Semaphor dar, das zum Warten innerhalb eines einzelnen Prozesses verwendet werden kann, wenn die Wartezeiten voraussichtlich sehr kurz sind. SemaphoreSlim benötigt möglichst viele von der Common Language Runtime (CLR) bereitgestellte Synchronisierungsprimitiven. Es stellt jedoch auch verzögert initialisierte, kernelbasierte Wait-Handles bereit, die notwendig sind, um das Warten auf mehrere Semaphore zu unterstützen. SemaphoreSlim unterstützt auch die Verwendung von Abbruchtoken, unterstützt jedoch keine benannten Semaphore oder die Verwendung eines Wait-Handles für die Synchronisierung.
Verwalten einer knappen Ressource
Threads wechseln in das Semaphor, indem sie die WaitOne-Methode aufrufen, die von der WaitHandle-Klasse geerbt wird. Bei der Rückgabe des Aufrufs wird der Zähler des Semaphors dekrementiert. Wenn ein Thread eine Aufnahme anfordert und der Zähler 0 (null) ist, dann wird der Thread blockiert. Da Threads das Semaphor freigeben, indem sie die Semaphore.Release-Methode aufrufen, wird blockierten Threads die Aufnahme gewährt. Für die Aufnahme von blockierten Threads in das Semaphor gibt es keine festgelegte Reihenfolge, z. B. First In, First Out (FIFO) oder Last In, First Out (LIFO).
Ein Thread kann mehrmals in das Semaphor wechseln, indem er wiederholt die WaitOne-Methode aufruft. Um das Semaphor freizugeben, kann der Thread entweder die Überladung der Release()-Methode genauso oft aufrufen oder die Überladung der Release(Int32)-Methode aufrufen und die Zahl der freizugebenden Wechsel angeben.
Semaphoren und Threadidentität
Die Semaphore-Klasse erzwingt keine Threadidentität bei Aufrufen der WaitOne-Methode und der Release-Methode. Beispielsweise werden Semaphoren häufig zusammen mit einem Producer- und einem Consumerthread verwendet, wobei der Zähler der Semaphoren immer von einem Thread inkrementiert und vom anderen Thread dekrementiert wird.
Vom Programmierer ist sicherzustellen, dass ein Semaphor von einem Thread nicht zu oft freigegeben wird. Angenommen, für ein Semaphor ist ein maximaler Zähler von 2 (zwei) festgelegt, und dem Semaphor wurden Thread A und Thread B hinzugefügt. Wenn Thread B durch einen Programmierfehler Release zweimal aufruft, dann sind beide Aufrufe erfolgreich. Die Anzahl für das Semaphor ist voll. Wenn Thread A schließlich Release aufruft, wird eine SemaphoreFullException ausgelöst.
Benannte Semaphoren
Das Windows-Betriebssystem ermöglicht es, Semaphoren zu benennen. Ein benanntes Semaphor ist systemweit sichtbar. Das heißt, dass das benannte Semaphor sofort nach seiner Erstellung in allen Prozessen und für alle Threads sichtbar ist. Ein benanntes Semaphor kann auf diese Weise dazu dienen, nicht nur Threads, sondern auch die Aktivitäten von Prozessen zu synchronisieren.
Sie können zur Darstellung eines benannten Systemsemaphors ein Semaphore-Objekt erstellen, indem Sie einen der Konstruktoren verwenden, die einen Namen angeben.
Hinweis |
---|
Da benannte Semaphoren systemweit sichtbar sind, besteht die Möglichkeit, zur Darstellung eines Semaphors mehrere Semaphore-Objekte zu verwenden.Bei jedem Aufruf eines Konstruktors oder der Semaphore.OpenExisting-Methode wird ein neues Semaphore-Objekt erstellt.Wenn Sie wiederholt denselben Namen verwenden, werden für die Darstellung desselben benannten Semaphors mehrere Objekte erstellt. |
Seien Sie vorsichtig, wenn Sie benannte Semaphore verwenden. Da sie systemweit sichtbar sind, kann ein anderer Prozess, der den gleichen Namen verwendet, unerwartet in das Semaphor aufgenommen werden. Bösartiger Code, der auf demselben Computer ausgeführt wird, könnte dies als Ausgangsbasis für einen Denial-of-Service-Angriff nutzen.
Verwenden Sie zum Schützen eines Semaphore-Objekts, das ein benanntes Semaphor darstellt, die Sicherheitseinstellungen der Zugriffssteuerung, vorzugsweise unter Verwendung eines Konstruktors, der ein System.Security.AccessControl.SemaphoreSecurity-Objekt angibt. Sie können die Sicherheitseinstellungen der Zugriffssteuerung auch bei der Verwendung der Semaphore.SetAccessControl-Methode nutzen. Allerdings kann hierbei die Sicherheitslücke zwischen Erstellung des Semaphors und Beginn des Schutzes nicht geschlossen werden. Das Schützen von Semaphoren mit den Sicherheitseinstellungen der Zugriffssteuerung ist bei der Abwehr bösartiger Angriffe hilfreich, löst aber das Problem unbeabsichtigter Namenskonflikte nicht.