Spinlock vs. Mutex: die wichtigsten Unterschiede
Spinlock und Mutex sind beides Sperren, die jeweils nur einen Thread gleichzeitig in einen kritischen Abschnitt lassen, unterscheiden sich aber darin, wie auf die Freigabe der Sperre gewartet wird. Ein Spinlock wartet aktiv (Busy-Waiting), indem er die Sperrvariable in einer Schleife ständig abfragt. Er belegt also auch während des Wartens die CPU, kann die Sperre aber sofort übernehmen, sobald sie frei wird. Ein Mutex legt den wartenden Thread schlafen und gibt die CPU ab; wird die Sperre freigegeben, weckt ihn das Betriebssystem. Bei sehr kurzer Haltedauer oder in Interrupt-Handlern, die nicht schlafen dürfen, verwendet man Spinlocks; bei langer Haltedauer oder wenn während des Haltens geschlafen werden könnte, Mutexe.
| Merkmal | Spinlock | Mutex |
|---|---|---|
| Warteverfahren | Fragt die Variable in einer Schleife ab, bis die Sperre frei ist (Busy-Waiting) | Ist die Sperre belegt, schläft der Thread und wird bei der Freigabe geweckt |
| CPU während des Wartens | Wird weiter belegt | Wird abgegeben. In dieser Zeit können andere Threads die CPU nutzen |
| Aufwand des Wartens | Kein Kontextwechsel; die Sperre kann sofort übernommen werden, sobald sie frei ist | Beim Einschlafen und Aufwachen fallen Systemaufrufe und Kontextwechsel an |
| Geeignete Haltedauer | Sehr kurz (kürzer als die Dauer eines Kontextwechsels) | Lang. Wenn während des Haltens geschlafen werden könnte, etwa beim Warten auf I/O |
| Schlafen während des Haltens | Verboten. Die wartende Seite würde die CPU weiter belegen | Möglich |
| Bei nur einem Kern | Während des Wartens kann der Thread, der die Sperre hält, nicht laufen; das Spinnen gibt sie nie frei. Im Kernel wird er mit abgeschalteter Präemption verwendet | Problemlos verwendbar |
| Einsatz im Kernel | Auch in Situationen nutzbar, in denen nicht geschlafen werden darf, etwa in Interrupt-Handlern (Interrupt-Kontext). Werden Daten mit einem Interrupt geteilt, werden vor dem Sperren die Interrupts gesperrt | Da er schlafen kann, nur im Prozesskontext verwendbar, nicht in Interrupt-Handlern |
| Prioritätsinversion | Wird der Thread, der die Sperre hält, angehalten, spinnt die wartende Seite weiter. Im Kernel wird dies durch Abschalten der Präemption während des Haltens verhindert | Abhilfe durch Mutexe mit Prioritätsvererbung |
| Implementierungsbeispiel | Die Variable wird mit atomaren Befehlen (Test-and-Set oder Compare-and-Swap) geändert. Test-and-Test-and-Set wartet normalerweise mit gewöhnlichen Lesezugriffen und verringert so die Kommunikation zwischen den Kernen | Bei futex unter Linux wird ohne Konkurrenz allein mit atomaren Befehlen im Userspace gesperrt; nur bei Konkurrenz legt der Kernel den Thread schlafen. Manche Implementierungen spinnen erst kurz und schlafen dann |
Die Zahlenwerte sind typische Größenordnungen und variieren je nach Prozessgeneration und Produkt.