Semaphorobjekte

Ein Semaphorobjekt ist ein Synchronisierungsobjekt, das eine Anzahl zwischen null und einem angegebenen Maximalwert beibehält. Die Anzahl wird jedes Mal dekrmentiert, wenn ein Thread eine Wartezeit auf das Semaphorobjekt abgeschlossen hat, und jedes Mal erhöht, wenn ein Thread den Semaphor freigibt. Wenn die Anzahl 0 erreicht, können keine weiteren Threads erfolgreich warten, bis der Zustand des Semaphorobjekts signalisiert wird. Der Status eines Semaphors wird auf „signalisiert“ festgelegt, wenn die Anzahl größer als Null ist, bzw. wird auf „nicht signalisiert“ gesetzt, wenn die Anzahl Null ist.

Das Semaphorobjekt ist nützlich, um eine freigegebene Ressource zu steuern, die eine begrenzte Anzahl von Benutzern unterstützen kann. Es fungiert als Gate, das die Anzahl von Threads, die die Ressource gemeinsam nutzen, auf eine angegebene maximale Anzahl beschränkt. Beispielsweise kann eine Anwendung die Anzahl von Fenstern, die sie erstellt, einschränken. Es verwendet einen Semaphor mit einer maximalen Anzahl, die dem Fensterlimit entspricht, wobei die Anzahl beim Erstellen eines Fensters dekrementiert und beim Schließen eines Fensters erhöht wird. Die Anwendung gibt das Semaphorobjekt im Aufruf einer der Wartefunktionen an, bevor jedes Fenster erstellt wird. Wenn die Anzahl 0 ist , was angibt, dass das Fensterlimit erreicht wurde, blockiert die Wartefunktion die Ausführung des Fenstererstellungscodes.

Ein Thread verwendet die Funktion CreateSemaphore oder CreateSemaphoreEx , um ein Semaphorobjekt zu erstellen. Der erstellenden Thread gibt die anfängliche Anzahl und den maximalen Wert der Anzahl für das Objekt an. Die anfängliche Anzahl darf weder kleiner als 0 noch größer als der Maximalwert sein. Der erstellenden Thread kann auch einen Namen für das Semaphorobjekt angeben. Threads in anderen Prozessen können ein Handle für ein vorhandenes Semaphorobjekt öffnen, indem sie seinen Namen in einem Aufruf der OpenSemaphore-Funktion angeben. Weitere Informationen zu Namen für Mutex-, Ereignis-, Semaphor- und Timerobjekte finden Sie unter Interprocess Synchronization.

Wenn mehr als ein Thread auf einen Semaphor wartet, wird ein wartenden Thread ausgewählt. Gehen Sie nicht von einer FIFO-Reihenfolge (First-In, First-Out) aus. Externe Ereignisse wie Kernelmodus-APCs können die Wartereihenfolge ändern.

Jedes Mal, wenn eine der Wartefunktionen zurückgegeben wird, weil der Zustand eines Semaphors auf signalisiert festgelegt wurde, wird die Anzahl des Semaphors um eins verringert. Die ReleaseSemaphore-Funktion erhöht die Anzahl eines Semaphors um eine angegebene Menge. Die Anzahl darf nie kleiner als 0 oder größer als der Maximalwert sein.

Die anfängliche Anzahl eines Semaphors wird in der Regel auf den Maximalwert festgelegt. Die Anzahl wird dann ab dieser Ebene verringert, wenn die geschützte Ressource verbraucht wird. Alternativ können Sie ein Semaphor mit einer anfänglichen Anzahl von 0 erstellen, um den Zugriff auf die geschützte Ressource zu blockieren, während die Anwendung initialisiert wird. Nach der Initialisierung können Sie ReleaseSemaphore verwenden, um die Anzahl auf den Maximalwert zu erhöhen.

Ein Thread, der ein Mutex-Objekt besitzt, kann wiederholt warten, bis dasselbe Mutex-Objekt signalisiert wird, ohne dass seine Ausführung blockiert wird. Ein Thread, der wiederholt auf dasselbe Semaphorobjekt wartet, verringert jedoch bei jedem Abschluss eines Wartevorgangs die Anzahl des Semaphors; Der Thread wird blockiert, wenn die Anzahl auf null steigt. Ebenso kann nur der Thread, der einen Mutex besitzt, die ReleaseMutex-Funktion erfolgreich aufrufen, obwohl jeder Thread ReleaseSemaphore verwenden kann, um die Anzahl eines Semaphorobjekts zu erhöhen.

Ein Thread kann die Anzahl eines Semaphors mehrmals verringern, indem er wiederholt dasselbe Semaphorobjekt in Aufrufen einer der Wartefunktionen angibt. Das Aufrufen einer der Wartefunktionen mit mehreren Objekten mit einem Array, das mehrere Handles desselben Semaphors enthält, führt jedoch nicht zu mehreren Dekrementen.

Wenn Sie die Verwendung des Semaphorobjekts abgeschlossen haben, rufen Sie die CloseHandle-Funktion auf, um das Handle zu schließen. Das Semaphorobjekt wird zerstört, wenn sein letztes Handle geschlossen wurde. Das Schließen des Handles wirkt sich nicht auf die Anzahl der Semaphore aus. Achten Sie daher darauf, ReleaseSemaphore aufzurufen, bevor Sie das Handle schließen oder bevor der Prozess beendet wird. Andernfalls wird bei ausstehenden Wartevorgängen ein Timeout ausgeführt oder unbegrenzt fortgesetzt, je nachdem, ob ein Timeoutwert angegeben wurde.

Verwenden von Semaphorobjekten