Cette documentation est archivée et n’est pas conservée.

Semaphore, classe

Remarque : cette classe est nouvelle dans le .NET Framework version 2.0.

Limite le nombre des threads qui peuvent accéder simultanément à une ressource ou un pool de ressources.

Espace de noms : System.Threading
Assembly : System (dans system.dll)

[ComVisibleAttribute(false)] 
public sealed class Semaphore : WaitHandle
/** @attribute ComVisibleAttribute(false) */ 
public final class Semaphore extends WaitHandle
ComVisibleAttribute(false) 
public final class Semaphore extends WaitHandle

RemarqueRemarque

L'attribut HostProtectionAttribute appliqué à cette classe a la valeur de propriété Resources suivante : Synchronization | ExternalThreading. HostProtectionAttribute n'affecte pas les applications bureautiques (qui sont généralement démarrées en double-cliquant sur une icône, en tapant une commande ou en entrant une URL dans un navigateur). Pour plus d'informations, consultez la classe HostProtectionAttribute ou Attributs de programmation et de protection des hôtes SQL Server.

Utilisez la classe Semaphore pour contrôler l'accès à un pool de ressources. Les threads entrent dans le sémaphore en appelant la méthode WaitOne, qui est héritée de la classe WaitHandle et qui libère le sémaphore en appelant la méthode Release.

Le compteur d'un sémaphore est décrémenté à chaque fois qu'un thread entre dans le sémaphore et incrémenté lorsqu'un thread libère le sémaphore. Lorsque le compteur est à zéro, les demandes suivantes sont bloquées jusqu'à ce que d'autres threads libèrent le sémaphore. Lorsque tous les threads ont libéré le sémaphore, le compteur est à la valeur maximale spécifiée lors de la création du sémaphore.

Il n'y a aucun ordre garanti d'entrée dans le sémaphore des threads bloqués, tel que premier entré premier sorti ou dernier entré premier sorti.

Un thread peut entrer plusieurs fois dans le sémaphore, en appelant la méthode WaitOne à plusieurs reprises. Pour libérer certaines de ces entrées ou toutes, le thread peut appeler la surcharge de méthode Release sans paramètre plusieurs fois ou la surcharge de méthode Release(Int32) qui spécifie le nombre d'entrées à libérer.

La classe Semaphore n'applique pas l'identité de thread sur les appels à WaitOne ou à Release. Il incombe au programmeur de garantir que les threads ne libèrent pas le sémaphore un trop grand nombre de fois. Par exemple, supposez qu'un sémaphore a un compteur d'une capacité de deux et que le thread A et le thread B entrent tous deux dans le sémaphore. Si une erreur de programmation dans thread B fait qu'il appelle Release deux fois, les deux appels aboutissent. Le compteur du sémaphore est complet et lorsque le thread A finit par appeler Release, une SemaphoreFullException est levée.

Les sémaphores sont de deux types : local et système nommé. Si vous créez un objet Semaphore à l'aide d'un constructeur qui accepte un nom, il est associé à un sémaphore système d'exploitation portant le même nom. Les sémaphores de système nommé sont visibles dans tout le système d'exploitation ; ils permettent de synchroniser les activités de processus. Vous pouvez créer plusieurs objets Semaphore qui représentent le même sémaphore système nommé et vous pouvez utiliser la méthode OpenExisting pour ouvrir un sémaphore système nommé existant.

Un sémaphore local existe uniquement dans votre processus. Il peut être utilisé par tout thread de votre processus qui a une référence à l'objet Semaphore local. Tous les objets Semaphore sont des sémaphores locaux séparés.

L'exemple de code suivant crée un sémaphore avec un nombre maximal égal à trois et un nombre initial égal à zéro. L'exemple démarre cinq threads, qui bloquent l'attente du sémaphore. Le thread principal utilise la méthode surchargée Release(Int32) pour augmenter le compteur du sémaphore à sa valeur maximale, en autorisant trois threads à entrer dans le sémaphore. Chaque thread utilise la méthode System.Threading.Thread.Sleep pour attendre une seconde, simuler le travail, puis appelle la méthode surchargée Release pour libérer le sémaphore. Chaque fois que le sémaphore est libéré, le compteur du sémaphore précédent est affiché. Les messages de la console suivent l'utilisation du sémaphore. L'intervalle de travail simulé augmente légèrement à chaque thread, pour faciliter la lecture de la sortie.

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

Les membres statiques publics (Shared en Visual Basic) de ce type sont thread-safe. Il n'est pas garanti que les membres d'instance soient thread-safe.

Windows 98, Windows 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Édition Media Center, Windows XP Professionnel Édition x64, Windows XP SP2, Windows XP Starter Edition

Le .NET Framework ne prend pas en charge toutes les versions de chaque plate-forme. Pour obtenir la liste des versions prises en charge, consultez Configuration requise.

.NET Framework

Prise en charge dans : 2.0
Afficher: