Mutex vs sémaphore : les différences expliquées

Un mutex protège une section critique pour qu'un seul thread à la fois puisse utiliser une ressource partagée, et le thread qui l'a verrouillé doit être celui qui le déverrouille. Un sémaphore est un compteur : il contrôle combien de threads peuvent utiliser une ressource limitée, et il peut aussi servir à signaler des événements d'un thread à un autre. Le mutex relève de la propriété et de l'exclusion ; le sémaphore du comptage et de la signalisation.

CritèreMutexSémaphore
ObjectifExclusion mutuelle : un seul thread à la fois dans une section critiqueComptage : limiter l'accès à un pool de N ressources, ou signaler des événements entre threads
ValeurVerrouillé ou déverrouillé (binaire)Un compteur entier non négatif (un sémaphore binaire est le cas particulier 0 ou 1)
PropriétéAppartient au thread qui l'a verrouillé, et ce thread doit le déverrouillerPas de propriétaire : n'importe quel thread peut faire un post ou signaler
OpérationsLock et unlockWait (P, décrémentation) et post (V, incrémentation)
Signalisation entre threadsNon prévu pour celaOui : par exemple un producteur qui signale un consommateur
Inversion de prioritéSouvent évitée grâce à l'héritage de prioritéGénéralement non prise en charge
Usages typiquesProtection d'une structure de données partagée comme une liste ou un compteurLimitation d'un pool de connexions, tampons producteur-consommateur bornés, signalisation d'un gestionnaire d'interruption vers une tâche
Pièges courantsInterblocage dû à un ordre de verrouillage incohérent, ou oubli du déverrouillageSignaux perdus et interblocage lorsque les compteurs ne correspondent pas

Les valeurs indiquées sont des ordres de grandeur typiques et varient selon la génération de procédé et le produit.

Quand choisir l'un ou l'autre ?

Mutex
Lorsque plusieurs threads accèdent aux mêmes données et qu'un seul peut le faire à la fois.
Sémaphore
Lorsqu'il faut limiter le nombre de threads utilisant une ressource, ou réveiller un thread lorsqu'un événement se produit.

Questions fréquentes

Un mutex est-il la même chose qu'un sémaphore binaire ?

Pas tout à fait. Les deux ont deux états, mais un mutex a un propriétaire qui doit le déverrouiller et prend souvent en charge l'héritage de priorité, tandis qu'un sémaphore n'a pas de propriétaire et peut être signalé par n'importe quel thread.

Quand a-t-on besoin d'un sémaphore à compteur ?

Lorsqu'il faut limiter le nombre de threads utilisant une ressource, comme un pool de N connexions, ou compter les éléments disponibles dans un tampon producteur-consommateur.

Qu'est-ce qu'un interblocage ?

Une situation où des threads s'attendent mutuellement indéfiniment, par exemple le thread A détient le verrou 1 et attend le verrou 2 tandis que le thread B détient le verrou 2 et attend le verrou 1. Prendre les verrous dans un ordre cohérent l'évite.

Quelle est la différence entre un spinlock et un mutex ?

Un spinlock effectue une attente active et convient aux attentes très courtes sur les systèmes multicœurs. Un mutex endort le thread en attente, ce qui est préférable pour les attentes plus longues.

Vérifier vos connaissances

Quelle comparaison entre mutex (verrou à attente en sommeil) et spinlock est correcte ?

  1. ALe mutex libère le CPU pendant l’attente et convient aux attentes longues, mais l’endormissement et le réveil imposent un coût à l’OS
  2. BLe mutex continue d’utiliser le CPU pendant l’attente et ne convient qu’aux attentes courtes
  3. CLe mutex et le spinlock sont la même chose sous des noms différents
Afficher la réponse et l'explication

Réponse : A. Le mutex libère le CPU pendant l’attente et convient aux attentes longues, mais l’endormissement et le réveil imposent un coût à l’OS

Lorsque le verrou n’est pas disponible, le mutex met le thread en attente et cède le CPU à d’autres threads ; l’OS le réveille à la libération du verrou. Ne gaspillant pas le CPU pendant l’attente, il convient aux attentes longues, mais l’endormissement, le réveil et le changement de contexte prennent quelques microsecondes. Les mutex des bibliothèques réelles combinent les avantages des deux, par exemple en tournant brièvement avant de s’endormir.

Quelle est l’utilisation la plus appropriée d’un sémaphore à compteur ?

  1. AToujours doubler la valeur d’une variable
  2. BRegrouper toute l’exécution du programme sur un seul thread
  3. CPermettre à 4 threads au plus d’utiliser simultanément une ressource dont le nombre d’utilisations simultanées est limité (par exemple 4 connexions au plus)
Afficher la réponse et l'explication

Réponse : C. Permettre à 4 threads au plus d’utiliser simultanément une ressource dont le nombre d’utilisations simultanées est limité (par exemple 4 connexions au plus)

Un sémaphore possède un compteur représentant le nombre restant ; on le décrémente avant utilisation (en attendant qu’il augmente s’il vaut 0) et on l’incrémente après utilisation. Avec une valeur initiale de 4, jusqu’à 4 threads peuvent utiliser la ressource simultanément. Avec une valeur initiale de 1, il sert à l’exclusion mutuelle comme un verrou. Les threads en attente sont généralement endormis et réveillés par l’OS.

Quelle description du verrou à attente active (spinlock) est correcte ?

  1. AVerrou qui endort le thread jusqu’à la libération et le fait réveiller par l’OS
  2. BVerrou qui attend la libération en examinant en boucle la variable de verrou
  3. CMécanisme qui protège les données en faisant tourner un disque
Afficher la réponse et l'explication

Réponse : B. Verrou qui attend la libération en examinant en boucle la variable de verrou

Le spinlock tente de prendre le verrou avec une instruction atomique et, en cas d’échec, réessaie immédiatement, de façon répétée. Sans le coût d’appeler l’OS pour s’endormir puis se réveiller, il est rapide lorsque le verrou n’est détenu que très brièvement. Il est très utilisé dans le noyau de l’OS et pour l’exclusion mutuelle avec les gestionnaires d’interruption. En revanche, il a l’inconvénient de continuer à consommer du CPU pendant l’attente.

  1. Quel est un exemple d’interblocage (deadlock) ?
  2. Quelle est la caractéristique d’un verrou lecteurs-rédacteurs (reader-writer lock) ?
  3. Lors d’une attente « jusqu’à ce que la file ne soit plus vide » avec une variable de condition, pourquoi revérifier la condition après le réveil avec une instruction while plutôt qu’avec une instruction if ?

Questions d'entraînement sur Multicœur et synchronisation

Termes clés expliqués

Mutex
Verrou qui ne peut être détenu que par un seul thread à la fois. En général, un thread qui ne peut l'obtenir est endormi et cède le CPU, puis réveillé par le système d'exploitation à la libération.
Sémaphore
Mécanisme de synchronisation doté d'un compteur représentant le nombre restant. On le décrémente de 1 avant usage (en attendant s'il vaut 0) et on l'incrémente de 1 après. Sert à gérer les ressources dont le nombre d'utilisations simultanées est limité.
Verrou tournant (spinlock)
Verrou dont l'attente consiste à tester en boucle la variable de verrou jusqu'à ce qu'il se libère. Rapide pour les attentes courtes, mais le CPU reste occupé pendant l'attente.
Interblocage (deadlock)
État où plusieurs threads détiennent chacun une ressource tout en attendant celle d'un autre, si bien qu'aucun ne peut avancer. On l'évite en fixant globalement l'ordre d'acquisition des verrous.

Comparatifs associés