Share via


Objets sémaphores

Un objet sémaphore est un objet de synchronisation qui conserve un nombre compris entre zéro et une valeur maximale spécifiée. Le nombre est décrémenté chaque fois qu’un thread termine une attente pour l’objet sémaphore et incrémenté chaque fois qu’un thread libère le sémaphore. Lorsque le nombre atteint zéro, plus aucun thread ne peut attendre que l’état de l’objet sémaphore soit signalé. L’état d’un sémaphore est défini sur « signalé » quand son nombre est supérieur à zéro et sur « non signalé » quand son nombre est égal à zéro.

L’objet sémaphore est utile pour contrôler une ressource partagée qui peut prendre en charge un nombre limité d’utilisateurs. Il agit comme une porte qui limite le nombre de threads qui partagent la ressource à un nombre maximal spécifié. Par exemple, une application peut limiter le nombre de fenêtres qu’elle crée. Il utilise un sémaphore avec un nombre maximal égal à la limite de fenêtre, décrémentant le nombre chaque fois qu’une fenêtre est créée et l’incrémentant chaque fois qu’une fenêtre est fermée. L’application spécifie l’objet sémaphore dans l’appel à l’une des fonctions d’attente avant la création de chaque fenêtre. Lorsque le nombre est égal à zéro, ce qui indique que la limite de fenêtre a été atteinte, la fonction wait bloque l’exécution du code de création de fenêtre.

Un thread utilise la fonction CreateSemaphore ou CreateSemaphoreEx pour créer un objet sémaphore. Le thread de création spécifie le nombre initial et la valeur maximale du nombre pour l’objet . Le nombre initial ne doit pas être inférieur à zéro ni supérieur à la valeur maximale. Le thread de création peut également spécifier un nom pour l’objet sémaphore. Les threads dans d’autres processus peuvent ouvrir un handle à un objet sémaphore existant en spécifiant son nom dans un appel à la fonction OpenSemaphore . Pour plus d’informations sur les noms des objets mutex, event, sémaphore et minuteur, consultez Synchronisation interprocess.

Si plusieurs threads sont en attente sur un sémaphore, un thread en attente est sélectionné. Ne supposez pas un ordre FIFO (premier entré, premier sorti). Les événements externes tels que les API en mode noyau peuvent modifier l’ordre d’attente.

Chaque fois qu’une des fonctions d’attente retourne parce que l’état d’un sémaphore a été défini sur signalé, le nombre de sémaphores est réduit d’un. La fonction ReleaseSemaphore augmente le nombre d’un sémaphore d’une quantité spécifiée. Le nombre ne peut jamais être inférieur à zéro ou supérieur à la valeur maximale.

Le nombre initial d’un sémaphore est généralement défini sur la valeur maximale. Le nombre est ensuite décrémenté à partir de ce niveau à mesure que la ressource protégée est consommée. Vous pouvez également créer un sémaphore avec un nombre initial de zéro pour bloquer l’accès à la ressource protégée pendant l’initialisation de l’application. Après l’initialisation, vous pouvez utiliser ReleaseSemaphore pour incrémenter le nombre jusqu’à la valeur maximale.

Un thread qui possède un objet mutex peut attendre à plusieurs reprises que le même objet mutex soit signalé sans que son exécution soit bloquée. Un thread qui attend à plusieurs reprises le même objet sémaphore, cependant, décrémente le nombre de sémaphores chaque fois qu’une opération d’attente est terminée ; le thread est bloqué lorsque le nombre atteint zéro. De même, seul le thread qui possède un mutex peut appeler correctement la fonction ReleaseMutex , bien que n’importe quel thread puisse utiliser ReleaseSemaphore pour augmenter le nombre d’objets sémaphores.

Un thread peut décrémenter le nombre d’un sémaphore plusieurs fois en spécifiant à plusieurs reprises le même objet sémaphore dans les appels à l’une des fonctions d’attente. Toutefois, l’appel d’une des fonctions d’attente à plusieurs objets avec un tableau qui contient plusieurs handles du même sémaphore n’entraîne pas de décrémentations multiples.

Lorsque vous avez terminé d’utiliser l’objet sémaphore, appelez la fonction CloseHandle pour fermer le handle. L’objet sémaphore est détruit lorsque son dernier handle a été fermé. La fermeture du handle n’affecte pas le nombre de sémaphores ; Par conséquent, veillez à appeler ReleaseSemaphore avant de fermer le handle ou avant l’arrêt du processus. Sinon, les opérations d’attente en attente expirent ou se poursuivent indéfiniment, selon qu’une valeur de délai d’attente a été spécifiée ou non.

Utilisation d’objets sémaphores