Spinlock vs mutex : les principales différences
Le spinlock et le mutex sont deux verrous qui ne laissent entrer qu’un seul thread à la fois dans une section critique, mais ils n’attendent pas de la même façon que le verrou se libère. Le spinlock attend activement en testant en boucle la variable du verrou : il continue d’utiliser le CPU pendant l’attente, mais prend le verrou dès qu’il se libère. Le mutex endort le thread en attente et libère le CPU ; lorsque le verrou est relâché, l’OS réveille le thread. On utilise le spinlock pour des durées de détention très courtes ou dans les gestionnaires d’interruption, qui ne peuvent pas dormir, et le mutex pour des détentions longues ou lorsque le thread risque de dormir pendant qu’il tient le verrou.
| Critère | Spinlock | Mutex |
|---|---|---|
| Mode d’attente | Teste la variable en boucle jusqu’à ce que le verrou se libère (attente active) | S’endort si le verrou est occupé et est réveillé lorsqu’il est libéré |
| CPU pendant l’attente | Continue de l’utiliser | Le libère. D’autres threads peuvent utiliser le CPU entre-temps |
| Coût de l’attente | Pas de changement de contexte ; le verrou est pris dès qu’il se libère | L’endormissement et le réveil coûtent des appels système et des changements de contexte |
| Durée de détention adaptée | Très courte (plus courte que la durée d’un changement de contexte) | Longue. Lorsque le thread risque de dormir pendant la détention, par exemple en attendant une E/S |
| Dormir en tenant le verrou | Interdit. Le côté en attente continuerait de consommer du CPU | Possible |
| Avec un seul cœur | Pendant l’attente, le thread qui tient le verrou ne peut pas s’exécuter : tourner en boucle ne libère pas le verrou. Dans le noyau, on l’utilise en désactivant la préemption | Fonctionne sans problème |
| Usage dans le noyau | Utilisable aussi là où l’on ne peut pas dormir, comme dans les gestionnaires d’interruption (contexte d’interruption). Pour des données partagées avec une interruption, on désactive les interruptions avant de prendre le verrou | Risque de dormir : utilisable uniquement en contexte de processus, pas dans les gestionnaires d’interruption |
| Inversion de priorité | Si le thread qui tient le verrou est interrompu, le côté en attente continue de tourner. Le noyau l’évite en désactivant la préemption pendant la détention | Peut être traitée par un mutex à héritage de priorité |
| Exemple d’implémentation | La variable est modifiée par des instructions atomiques (test-and-set ou compare-and-swap). Le test-and-test-and-set attend normalement par des lectures ordinaires, ce qui réduit les communications entre cœurs | Avec le futex de Linux, en l’absence de contention, le verrouillage se fait uniquement par des instructions atomiques en espace utilisateur ; ce n’est qu’en cas de contention que le noyau endort le thread. Certaines implémentations tournent un peu avant de dormir |
Les valeurs indiquées sont des ordres de grandeur typiques et varient selon la génération de procédé et le produit.