Partager via


Semaphore et SemaphoreSlim

La classe System.Threading.Semaphore représente un sémaphore nommé (systemwide) ou local. Il s'agit d'un wrapper mince autour de l'objet de sémaphore Win32. Les sémaphores Win32 sont des sémaphores de décompte, qui peuvent être utilisés pour contrôler l'accès à un pool de ressources.

La classe SemaphoreSlim représente un sémaphore léger et rapide qui peut être utilisé pour l'attente dans un processus unique lorsque les temps d'attente sont supposés être très courts. SemaphoreSlim repose autant que possible sur les primitives de synchronisation fournies par le Common Language Runtime (CLR). Toutefois, il fournit également les handles d'attente basés sur le noyau initialisés de façon tardive nécessaires pour prendre en charge l'attente sur plusieurs sémaphores. SemaphoreSlim prend également en charge l'utilisation de jetons d'annulation, mais ne prend pas en charge les sémaphores nommés ou l'utilisation d'un handle d'attente pour la synchronisation.

Gestion d'une ressource limitée

Les threads entrent dans le sémaphore en appelant la méthode WaitOne qui est héritée de la classe WaitHandle. Lorsque l'appel est retourné, le décompte sur le sémaphore est décrémenté. Lorsqu'un thread demande à entrer et que le décompte est égal à zéro, le thread se bloque. Lorsque les threads libèrent le sémaphore en appelant la méthode Semaphore.Release, les threads bloqués sont autorisés à entrer. Il n'y a aucun ordre garanti d'entrée dans le sémaphore des threads bloqués, tel que premier entré premier sorti (FIFO) ou dernier entré premier sorti (LIFO).

Un thread peut entrer plusieurs fois dans le sémaphore en appelant la méthode WaitOne à plusieurs reprises. Pour libérer le sémaphore, le thread peut appeler la surcharge de la méthode Release() autant de fois ou appeler la surcharge de la méthode Release(Int32) et spécifier le nombre d'entrées à libérer.

Sémaphores et identité de thread

La classe Semaphore n'applique pas l'identité de thread sur les appels aux méthodes WaitOne et Release. Par exemple, un scénario d'utilisation classique pour les sémaphores implique un thread producteur et un thread consommateur, un thread incrémentant toujours le nombre de sémaphores et l'autre le décrémentant.

Il est de la responsabilité du programmeur de garantir qu'un thread ne libère pas le sémaphore trop souvent. Par exemple, supposons que le décompte maximal d'un sémaphore est de deux et que le thread A et le thread B entrent dans le sémaphore. Si une erreur de programmation dans le thread B le conduit à appeler Release deux fois, les deux appels aboutissent. Le décompte sur le sémaphore est complet, et lorsque le thread A appelle enfin Release, une SemaphoreFullException est levée.

Sémaphores nommés

Le système d'exploitation Windows permet aux sémaphores d'avoir des noms. Un sémaphore nommé est à l'échelle du système. Cela signifie qu'une fois que le sémaphore nommé est créé, il est visible pour tous les threads de tous les processus. Ainsi, les sémaphores nommés peuvent être utilisés pour synchroniser les activités de processus ainsi que les threads.

Vous pouvez créer un objet Semaphore représentant un sémaphore système nommé en utilisant l'un des constructeurs qui spécifient un nom.

RemarqueRemarque

Étant donné que les sémaphores nommés sont à l'échelle du système, il est possible que plusieurs objets Semaphore représentent le même sémaphore nommé.Chaque fois vous appelez un constructeur ou la méthode Semaphore.OpenExisting, un nouvel objet Semaphore est créé.La spécification du même nom à plusieurs reprises crée différents objets qui représentent le même sémaphore nommé.

Soyez prudent lorsque vous utilisez des sémaphores nommés. Étant donné qu'ils sont à l'échelle du système, un autre processus utilisant le même nom peut entrer dans votre sémaphore de manière inattendue. Un code nuisible en exécution sur le même ordinateur pourrait l'utiliser comme base d'une attaque par déni de service.

Utilisez la sécurité du contrôle d'accès pour protéger un objet Semaphore qui représente un sémaphore nommé, en utilisant de préférence un constructeur qui spécifie un objet System.Security.AccessControl.SemaphoreSecurity. Vous pouvez également appliquer la sécurité du contrôle d'accès à l'aide de la méthode Semaphore.SetAccessControl, mais la période entre la création du sémaphore et le moment où il est protégé présente des risques. La protection des sémaphores à l'aide de la sécurité du contrôle d'accès empêche les attaques malveillantes, mais ne résout pas le problème des collisions de noms involontaires.

Voir aussi

Référence

Semaphore

SemaphoreSlim

Autres ressources

Fonctionnalités et objets de threading