6. Sémaphores
6.1 Modèle
Un sémaphore de Dijkstra comprend :
- un compteur
Kde permissions ou de ressources disponibles; - une file
Lde participants bloqués.
Deux opérations atomiques le manipulent :
- P, down ou wait : si une permission est disponible, la consommer; sinon placer l’appelant en attente;
- V, up, signal ou post : réveiller un attenteur, ou augmenter le nombre de permissions si personne n’attend.
Une file FIFO produit un sémaphore fort et limite la famine. Une politique non équitable, par exemple LIFO, peut laisser un ancien attenteur indéfiniment en file.
6.2 Comptage, binaire et ordre
- Un sémaphore de comptage représente plusieurs ressources interchangeables.
- Un sémaphore binaire ne prend que les états 0 et 1 et peut servir à l’exclusion, sans acquérir automatiquement la sémantique de propriété d’un mutex.
- Un sémaphore initialisé à 0 peut imposer un ordre : une tâche exécute S1 puis effectue
post; l’autre attend avant S2. Ainsi, S1 précède toujours S2.
6.3 Producteur-consommateur corrigé
Code (text) · sélectionner pour copier
producteur consommateur
produce() down(full)
down(empty) down(mutex)
down(mutex) retirer de la file
insérer dans la file up(mutex)
up(mutex) up(empty)
up(full) consume()
Initialisation :
empty = N: nombre de places libres;full = 0: nombre d’éléments disponibles;mutex = 1: accès exclusif à la structure.
Il faut acquérir le sémaphore de ressource avant le mutex. Sinon, un thread pourrait dormir en conservant le mutex dont l’autre a besoin pour rendre la ressource disponible.
6.4 API POSIX des sémaphores
- POSIX distingue les sémaphores nommés et non nommés; les références du module détaillent surtout le cycle de vie des objets non nommés.
sem_init(&s, pshared, value)initialise un sémaphore non nommé.pshared == 0le limite aux threads du même processus; une valeur non nulle exige une mémoire réellement partagée entre processus.sem_waitdécrémente ou bloque.sem_trywaitretourne immédiatement avecEAGAIN;sem_timedwaitutilise une échéance absolue. Une interruption par signal peut produireEINTR.sem_postrend une permission et peut réveiller un attenteur. L’appel est async-signal-safe; dépasserSEM_VALUE_MAXproduitEOVERFLOW.sem_getvaluepermet de consulter la valeur exposée par l’implantation, mais cette observation instantanée ne remplace pas une opération atomique de synchronisation.sem_destroydoit être appelé avant de libérer la mémoire, mais seulement lorsqu’aucun participant n’attend. Réinitialiser un sémaphore actif ou le détruire pendant une attente mène à un comportement indéfini.