Partage via


Semaphore Classe

Définition

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

public ref class Semaphore sealed : System::Threading::WaitHandle
public sealed class Semaphore : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(false)]
public sealed class Semaphore : System.Threading.WaitHandle
type Semaphore = class
    inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(false)>]
type Semaphore = class
    inherit WaitHandle
Public NotInheritable Class Semaphore
Inherits WaitHandle
Héritage
Semaphore
Héritage
Attributs

Exemples

L’exemple de code suivant crée un sémaphore avec un nombre maximal de trois et un nombre initial de zéro. L’exemple démarre cinq threads, qui bloquent l’attente du sémaphore. Le thread main utilise la Release(Int32) surcharge de méthode pour augmenter le nombre de sémaphores à son maximum, ce qui permet à trois threads d’entrer dans le sémaphore. Chaque thread utilise la Thread.Sleep méthode pour attendre une seconde, simuler le travail, puis appelle la surcharge de méthode Release() pour libérer le sémaphore. Chaque fois que le sémaphore est libéré, le nombre de sémaphores précédent est affiché. Les messages de console suivent l’utilisation du sémaphore. L’intervalle de travail simulé est légèrement augmenté pour chaque thread, afin de faciliter la lecture de la sortie.

#using <System.dll>
using namespace System;
using namespace System::Threading;

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

   // A padding interval to make the output more orderly.
   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 = gcnew Semaphore( 0,3 );
      
      // Create and start five numbered threads.
      //
      for ( int i = 1; i <= 5; i++ )
      {
         Thread^ t = gcnew Thread(
            gcnew 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( L"Main thread calls Release(3)." );
      _pool->Release( 3 );

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

private:
   static void Worker( Object^ num )
   {
      // Each worker thread begins by requesting the
      // semaphore.
      Console::WriteLine( L"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( L"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( L"Thread {0} releases the semaphore.", num );
      Console::WriteLine( L"Thread {0} previous semaphore count: {1}",
         num, _pool->Release() );
   }
};
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(initialCount: 0, maximumCount: 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(releaseCount: 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());
    }
}
Imports System.Threading

Public Class Example

    ' A semaphore that simulates a limited resource pool.
    '
    Private Shared _pool As Semaphore

    ' A padding interval to make the output more orderly.
    Private Shared _padding As Integer

    <MTAThread> _
    Public Shared Sub 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 i As Integer = 1 To 5
            Dim t As New Thread(New ParameterizedThreadStart(AddressOf Worker))
            'Dim t As New Thread(AddressOf Worker)

            ' Start the thread, passing the number.
            '
            t.Start(i)
        Next 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.")
    End Sub

    Private Shared Sub Worker(ByVal num As Object)
        ' 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.
        Dim padding As Integer = 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.
        '
        Thread.Sleep(1000 + padding)

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

Remarques

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

Le nombre sur 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 nombre est égal à zéro, les requêtes suivantes se bloquent jusqu’à ce que d’autres threads libèrent le sémaphore. Lorsque tous les threads ont libéré le sémaphore, le nombre est à la valeur maximale spécifiée lors de la création du sémaphore.

Il n’existe aucun ordre garanti, tel que FIFO ou LIFO, dans lequel les threads bloqués entrent dans le sémaphore.

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

La Semaphore classe n’applique pas l’identité de thread aux appels à WaitOne ou Release. Il incombe au programmeur de s’assurer que les threads ne libèrent pas trop de fois le sémaphore. Supposons, par exemple, qu'un sémaphore ait un nombre maximal égal à deux et que le thread A et le thread B entrent dans le sémaphore. Si une erreur de programmation dans le thread B entraîne un double appel Release, les deux appels aboutiront. Le nombre maximal du sémaphore sera alors atteint, et quand le thread A appellera Release, une exception SemaphoreFullException sera levée.

Les sémaphores sont de deux types : les sémaphores locaux et les sémaphores système nommés. Si vous créez un Semaphore objet à l’aide d’un constructeur qui accepte un nom, il est associé à un sémaphore de système d’exploitation de ce nom. Les sémaphores système nommés sont visibles dans tout le système d’exploitation et peuvent être utilisés pour synchroniser les activités des processus. Vous pouvez créer plusieurs Semaphore objets qui représentent le même sémaphore système nommé, et vous pouvez utiliser la OpenExisting méthode 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. Chaque Semaphore objet est un sémaphore local distinct.

Attention

Par défaut, un sémaphore nommé n’est pas limité à l’utilisateur qui l’a créé. D’autres utilisateurs peuvent être en mesure d’ouvrir et d’utiliser le sémaphore, notamment en interférant avec le sémaphore en acquérant le sémaphore plusieurs fois et en ne le libérant pas. Pour restreindre l’accès à des utilisateurs spécifiques, vous pouvez utiliser une surcharge de constructeur ou SemaphoreAcl passer un SemaphoreSecurity lors de la création du sémaphore nommé. Évitez d’utiliser des sémaphores nommés sans restrictions d’accès sur les systèmes qui peuvent avoir des utilisateurs non approuvés exécutant du code.

Constructeurs

Semaphore(Int32, Int32)

Initialise une nouvelle instance de la classe Semaphore en spécifiant le nombre initial d’entrées et le nombre maximal d’entrées simultanées.

Semaphore(Int32, Int32, String)

Initialise une nouvelle instance de la classe Semaphore en spécifiant le nombre initial d'entrées et le nombre maximal d'entrées simultanées, et en spécifiant en option le nom d'un objet sémaphore système.

Semaphore(Int32, Int32, String, Boolean)

Initialise une nouvelle instance de la classe Semaphore en spécifiant le nombre initial d'entrées et le nombre maximal d'entrées simultanées, en spécifiant en option le nom d'un objet sémaphore système et en spécifiant une variable qui reçoit une valeur indiquant si un sémaphore système a été créé.

Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity)

Initialise une nouvelle instance de la classe Semaphore en spécifiant le nombre initial d'entrées et le nombre maximal d'entrées simultanées, en spécifiant en option le nom d'un objet sémaphore système et en spécifiant une variable qui reçoit une valeur indiquant si un nouveau sémaphore système a été créé et spécifiant le contrôle d'accès de sécurité pour le sémaphore système.

Champs

WaitTimeout

Indique que le délai fixé pour une opération WaitAny(WaitHandle[], Int32, Boolean) a été dépassé sans qu'aucun des handles d'attente n'ait été signalé. Ce champ est constant.

(Hérité de WaitHandle)

Propriétés

Handle
Obsolète.
Obsolète.

Obtient ou définit le handle du système d'exploitation natif.

(Hérité de WaitHandle)
SafeWaitHandle

Obtient ou définit le handle du système d'exploitation natif.

(Hérité de WaitHandle)

Méthodes

Close()

Libère toutes les ressources détenues par le WaitHandle actuel.

(Hérité de WaitHandle)
CreateObjRef(Type)

Crée un objet contenant toutes les informations appropriées requises pour générer un proxy permettant de communiquer avec un objet distant.

(Hérité de MarshalByRefObject)
Dispose()

Libère toutes les ressources utilisées par l'instance actuelle de la classe WaitHandle.

(Hérité de WaitHandle)
Dispose(Boolean)

En cas de substitution dans une classe dérivée, libère les ressources non managées utilisées par WaitHandle et libère éventuellement les ressources managées.

(Hérité de WaitHandle)
Equals(Object)

Détermine si l'objet spécifié est égal à l'objet actuel.

(Hérité de Object)
GetAccessControl()

Reçoit la sécurité de contrôle d'accès pour un sémaphore système nommé.

GetHashCode()

Fait office de fonction de hachage par défaut.

(Hérité de Object)
GetLifetimeService()
Obsolète.

Récupère l'objet de service de durée de vie en cours qui contrôle la stratégie de durée de vie de cette instance.

(Hérité de MarshalByRefObject)
GetType()

Obtient le Type de l'instance actuelle.

(Hérité de Object)
InitializeLifetimeService()
Obsolète.

Obtient un objet de service de durée de vie pour contrôler la stratégie de durée de vie de cette instance.

(Hérité de MarshalByRefObject)
MemberwiseClone()

Crée une copie superficielle du Object actuel.

(Hérité de Object)
MemberwiseClone(Boolean)

Crée une copie superficielle de l'objet MarshalByRefObject actuel.

(Hérité de MarshalByRefObject)
OpenExisting(String)

Ouvre le sémaphore nommé spécifié s'il existe déjà.

OpenExisting(String, SemaphoreRights)

Ouvre le sémaphore nommé spécifié, s'il existe déjà, avec l'accès de sécurité souhaité.

Release()

Quitte le sémaphore et retourne le compteur antérieur.

Release(Int32)

Quitte le sémaphore un nombre spécifié de fois et retourne le compteur précédent.

SetAccessControl(SemaphoreSecurity)

Définit la sécurité de contrôle d'accès pour un sémaphore système nommé.

ToString()

Retourne une chaîne qui représente l'objet actuel.

(Hérité de Object)
TryOpenExisting(String, Semaphore)

Ouvre le sémaphore nommé spécifié, s'il existe déjà, et retourne une valeur indiquant si l'opération a réussi.

TryOpenExisting(String, SemaphoreRights, Semaphore)

Ouvre le sémaphore nommé spécifié, s'il existe déjà, avec l'accès de sécurité souhaité, puis retourne une valeur indiquant si l'opération a réussi.

WaitOne()

Bloque le thread actuel jusqu'à ce que le WaitHandle actuel reçoive un signal.

(Hérité de WaitHandle)
WaitOne(Int32)

Bloque le thread actuel jusqu'à ce que le WaitHandle actuel reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l'intervalle de temps.

(Hérité de WaitHandle)
WaitOne(Int32, Boolean)

Bloque le thread actuel jusqu’à ce que le WaitHandle actuel reçoive un signal, en utilisant un entier signé 32 bits pour spécifier l’intervalle de temps et en spécifiant s’il faut quitter le domaine de synchronisation avant l’attente.

(Hérité de WaitHandle)
WaitOne(TimeSpan)

Bloque le thread actuel jusqu'à ce que l'instance actuelle reçoive un signal, en utilisant une valeur TimeSpan pour spécifier l'intervalle de temps.

(Hérité de WaitHandle)
WaitOne(TimeSpan, Boolean)

Bloque le thread actuel jusqu'à ce que l'instance actuelle reçoive un signal, en utilisant une valeur TimeSpan pour spécifier l'intervalle de temps et en spécifiant s'il faut quitter le domaine de synchronisation avant l'attente.

(Hérité de WaitHandle)

Implémentations d’interfaces explicites

IDisposable.Dispose()

Cette API prend en charge l'infrastructure du produit et n'est pas destinée à être utilisée directement à partir de votre code.

Libère toutes les ressources utilisées par WaitHandle.

(Hérité de WaitHandle)

Méthodes d’extension

GetAccessControl(Semaphore)

Retourne les descripteurs de sécurité pour le semaphore spécifié.

SetAccessControl(Semaphore, SemaphoreSecurity)

Définit les descripteurs de sécurité pour le sémaphore spécifié.

GetSafeWaitHandle(WaitHandle)

Obtient le handle sécurisé pour un handle d’attente de système d’exploitation natif.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Définit un handle sécurisé pour un handle d’attente de système d’exploitation natif.

S’applique à

Cohérence de thread

Ce type est thread-safe.

Voir aussi