Diese Dokumentation wurde archiviert und wird nicht länger gepflegt.

Semaphore-Klasse

Aktualisiert: November 2007

Schränkt die Anzahl von Threads ein, die gleichzeitig auf eine Ressource oder einen Pool von Ressourcen zugreifen können.

Namespace:  System.Threading
Assembly:  System (in System.dll)

[ComVisibleAttribute(false)]
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, 
	ExternalThreading = true)]
public sealed class Semaphore : WaitHandle
/** @attribute ComVisibleAttribute(false) */
/** @attribute HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true) */
public final class Semaphore extends WaitHandle
public final class Semaphore extends WaitHandle

kt3k0k2h.alert_note(de-de,VS.90).gifHinweis:

Das auf diesen Typ oder Member angewendete HostProtectionAttribute-Attribut besitzt den folgenden Resources-Eigenschaftenwert: Synchronization | ExternalThreading. Das HostProtectionAttribute hat keine Auswirkungen auf Desktopanwendungen (die normalerweise durch Doppelklicken auf ein Symbol, Eingeben eines Befehls oder einer URL in einem Browser gestartet werden). Weitere Informationen finden Sie unter der HostProtectionAttribute-Klasse oder unter SQL Server-Programmierung und Hostschutzattribute.

Steuern Sie mithilfe der Semaphore-Klasse den Zugriff auf einen Pool von Ressourcen. Threads wechseln in das Semaphor, indem sie die WaitOne-Methode aufrufen, die von der WaitHandle-Klasse geerbt wird, und geben das Semaphor durch Aufrufen der Release-Methode frei.

Der Zähler für ein Semaphor verringert sich jedes Mal, wenn dem Semaphor ein Thread hinzugefügt wird, und er erhöht sich, wenn ein Thread das Semaphor freigibt. Wenn der Zähler 0 (null) ist, werden nachfolgende Anforderungen blockiert, bis andere Threads das Semaphor freigeben. Wenn alle Threads das Semaphor freigegeben haben, hat der Zähler den maximalen Wert, der beim Erstellen des Semaphors angegeben wurde.

Es gibt keine garantierte Reihenfolge (wie FIFO oder LIFO), in der dem Semaphor blockierte Threads hinzugefügt werden.

Ein Thread kann mehrmals in das Semaphor aufgenommen werden, indem die WaitOne-Methode wiederholt aufgerufen wird. Um mehrere oder alle dieser Einträge freizugeben, kann der Thread die Überladung der Release()-Methode ohne Parameter mehrfach aufrufen, oder er kann die Überladung der Release(Int32)-Methode aufrufen, die die Anzahl der freizugebenden Einträge angibt.

Die Semaphore-Klasse erzwingt keine Threadidentität für Aufrufe von WaitOne oder Release. Der Programmierer muss gewährleisten, dass Threads das Semaphor nicht zu oft freigeben. 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, sind beide Aufrufe erfolgreich. Der Zähler des Semaphors ist voll, und wenn Thread A Release aufruft, wird eine SemaphoreFullException ausgelöst.

Es gibt zwei Typen von Semaphoren: lokale Semaphore und benannte Systemsemaphore. Wenn Sie ein Semaphore-Objekt mit einem Konstruktor erstellen, der einen Namen akzeptiert, wird das Objekt einem Betriebssystemsemaphor mit demselben Namen zugeordnet. Benannte Systemsemaphore sind innerhalb des Betriebssystems sichtbar und können verwendet werden, um die Aktivitäten von Prozessen zu synchronisieren. Sie können mehrere Semaphore-Objekte erstellen, die dasselbe benannte Systemsemaphor darstellen, und Sie können ein vorhandenes benanntes Systemsemaphor mithilfe der OpenExisting-Methode öffnen.

Ein lokales Semaphor ist nur innerhalb des Prozesses vorhanden. Es kann von jedem Thread innerhalb des Prozesses verwendet werden, der über einen Verweis auf das lokale Semaphore-Objekt verfügt. Jedes Semaphore-Objekt ist ein separates lokales Semaphor.

Im folgenden Codebeispiel wird ein Semaphor mit einem maximalen Zähler von 3 (drei) und einem anfänglichen Zähler von 0 (null) erstellt. Im Beispiel werden fünf Threads gestartet, die blockiert sind und auf das Semaphor warten. Der Hauptthread verwendet die Überladung der Release(Int32)-Methode, um den Zähler des Semaphors auf seinen Maximalwert zu setzen, sodass dem Semaphor drei Threads hinzugefügt werden können. Jeder Thread verwendet die Thread.Sleep-Methode, um eine Sekunde lang zu warten und Arbeit zu simulieren, und ruft dann die Überladung der Release()-Methode auf, um das Semaphor freizugeben. Jedes Mal, wenn das Semaphor freigegeben wird, wird der vorherige Semaphorzähler angezeigt. Die Verwendung des Semaphors wird durch Konsolenmeldungen überwacht. Das simulierte Arbeitsintervall wird für jeden Thread leicht erhöht, damit die Ausgabe leichter zu lesen ist.

using System;
using System.Threading;

public class Example
{
    // A semaphore that simulates a limited resource pool.
    //
    private static Semaphore _pool;

    // A padding interval to make the output more orderly.
    private static int _padding;

    public static void Main()
    {
        // Create a semaphore that can satisfy up to three
        // concurrent requests. Use an initial count of zero,
        // so that the entire semaphore count is initially
        // owned by the main program thread.
        //
        _pool = new Semaphore(0, 3);

        // Create and start five numbered threads. 
        //
        for(int i = 1; i <= 5; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Worker));

            // Start the thread, passing the number.
            //
            t.Start(i);
        }

        // Wait for half a second, to allow all the
        // threads to start and to block on the semaphore.
        //
        Thread.Sleep(500);

        // The main thread starts out holding the entire
        // semaphore count. Calling Release(3) brings the 
        // semaphore count back to its maximum value, and
        // allows the waiting threads to enter the semaphore,
        // up to three at a time.
        //
        Console.WriteLine("Main thread calls Release(3).");
        _pool.Release(3);

        Console.WriteLine("Main thread exits.");
    }

    private static void Worker(object num)
    {
        // Each worker thread begins by requesting the
        // semaphore.
        Console.WriteLine("Thread {0} begins " +
            "and waits for the semaphore.", num);
        _pool.WaitOne();

        // A padding interval to make the output more orderly.
        int padding = Interlocked.Add(ref _padding, 100);

        Console.WriteLine("Thread {0} enters the semaphore.", num);

        // The thread's "work" consists of sleeping for 
        // about a second. Each thread "works" a little 
        // longer, just to make the output more orderly.
        //
        Thread.Sleep(1000 + padding);

        Console.WriteLine("Thread {0} releases the semaphore.", num);
        Console.WriteLine("Thread {0} previous semaphore count: {1}",
            num, _pool.Release());
    }
}


import System.*;
import System.Threading.*;

public class Example
{
    // A semaphore that simulates a limited resource pool.
    //
    private static Semaphore _pool;

    // A padding interval to make the output more orderly.
    private static int _padding;

    public static void main(String[] args)
    {
        // Create a semaphore that can satisfy up to three
        // concurrent requests. Use an initial count of zero,
        // so that the entire semaphore count is initially
        // owned by the main program thread.
        //
        _pool = new Semaphore(0, 3);
        // Create and start five numbered threads. 
        //
        for (int i = 1; i <= 5; i++) {
            System.Threading.Thread t = new System.Threading.Thread(new 
                ParameterizedThreadStart(Worker));
            // Start the thread, passing the number.
            //
            t.Start((Int32)i);
        }
        // Wait for half a second, to allow all the
        // threads to start and to block on the semaphore.
        //
        System.Threading.Thread.Sleep(500);
        // The main thread starts out holding the entire
        // semaphore count. Calling Release(3) brings the 
        // semaphore count back to its maximum value, and
        // allows the waiting threads to enter the semaphore,
        // up to three at a time.
        //
        Console.WriteLine("main thread calls Release(3).");
        _pool.Release(3);

        Console.WriteLine("main thread exits.");
    } //main

    private static void Worker(Object num)
    {
        // Each worker thread begins by requesting the
        // semaphore.
        Console.WriteLine("Thread {0} begins " 
            + "and waits for the semaphore.", num);
        _pool.WaitOne();
        // A padding interval to make the output more orderly.
        int padding = Interlocked.Add(_padding, 100);

        Console.WriteLine("Thread {0} enters the semaphore.", num);
        // The thread's "work" consists of sleeping for 
        // about a second. Each thread "works" a little 
        // longer, just to make the output more orderly.
        //
        System.Threading.Thread.Sleep(1000 + padding);

        Console.WriteLine("Thread {0} releases the semaphore.", num);
        Console.WriteLine("Thread {0} previous semaphore count: {1}", num, 
            (Int32)_pool.Release());
    } //Worker
} //Example


Dieser Typ ist threadsicher.

Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

.NET Framework und .NET Compact Framework unterstützen nicht alle Versionen sämtlicher Plattformen. Eine Liste der unterstützten Versionen finden Sie unter Systemanforderungen für .NET Framework.

.NET Framework

Unterstützt in: 3.5, 3.0, 2.0
Anzeigen: