Partager 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, aucun autre 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é lorsque son nombre est supérieur à zéro et non signé lorsque 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 placer une limite sur 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 incrémentée chaque fois qu’une fenêtre est fermée. L’application spécifie l’objet sémaphore en appel à l’une des fonctions d’attente avant la création de chaque fenêtre. Lorsque le nombre est égal à zéro , indiquant que la limite de fenêtre a été atteinte, la fonction d’attente 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 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 de synchronisation interprocess.

Si plusieurs threads attendent un sémaphore, un thread en attente est sélectionné. Ne supposez pas une commande fiFO (first-out). 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 diminué d’un. La fonction ReleaseSemaphore augmente le nombre d’un sémaphore par 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, car 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 à la valeur maximale.

Un thread propriétaire d’un objet mutex peut attendre à plusieurs reprises que le même objet mutex devienne signalé sans que son exécution ne soit bloquée. Un thread qui attend à plusieurs reprises le même objet sémaphore, toutefois, 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 est égal à zéro. De même, seul le thread propriétaire d’un mutex peut appeler correctement la fonction ReleaseMutex, bien que n’importe quel thread puisse utiliser ReleaseSemaphore pour augmenter le nombre d’un objet sémaphore.

Un thread peut décrémenter le nombre de sémaphores 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 sa dernière poignée a été fermée. 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 la fin du processus. Sinon, les opérations d’attente en attente expirent ou continuent indéfiniment, selon qu’une valeur de délai d’attente a été spécifiée.

à l’aide d’objets sémaphores