Spinlock vs Mutex: Key Differences Explained

Spinlocks and mutexes are both locks that admit only one thread at a time into a critical section, but they differ in how they wait for the lock to become free. A spinlock waits by busy-waiting, repeatedly checking the lock variable in a loop, so it keeps using the CPU while waiting but can take the lock immediately once it is free. A mutex puts the waiting thread to sleep, giving up the CPU, and has the OS wake it when the lock is released. Use a spinlock when the hold time is very short or inside an interrupt handler that cannot sleep, and a mutex when the lock is held for a long time or the holder may sleep.

AspectSpinlockMutex
How it waitsRepeatedly checks the variable in a loop until the lock is free (busy-waiting)If the lock is not free, sleeps and is woken when it is released
CPU while waitingKeeps using itGives it up. Other threads can use the CPU meanwhile
Waiting overheadNo context switch; takes the lock immediately once it is freeSystem calls and context switches add overhead when sleeping and waking
Suitable hold timeVery short (shorter than the time a context switch takes)Long. When the holder may sleep, such as waiting for I/O while holding the lock
Sleeping while holdingNot allowed. Waiters would keep using the CPUAllowed
On a single coreWhile a thread waits, the lock holder cannot run, so spinning never frees the lock. In the kernel it is used with preemption disabledWorks without problems
Use in the kernelUsable even where sleeping is not allowed, such as interrupt handlers (interrupt context). When sharing data with an interrupt, disable interrupts before taking itMay sleep, so usable only in process context, not in interrupt handlers
Priority inversionIf the lock holder is preempted, waiters keep spinning. The kernel prevents this by disabling preemption while the lock is heldCan be addressed with priority-inheritance mutexes
Implementation examplesAtomic instructions (test-and-set or compare-and-swap) update the variable. Test-and-test-and-set waits with ordinary reads to reduce inter-core trafficLinux futex locks with only user-space atomic instructions when uncontended and asks the kernel to put the thread to sleep only on contention. Some implementations spin briefly before sleeping

Figures are typical orders of magnitude and vary by process generation and product.

When to use which

Spinlock
On multicore systems when the lock is held for a very short time (shorter than the context-switch overhead). Kernel code where sleeping is not allowed, such as interrupt handlers.
Mutex
When the lock is held for a long time, or the holder may sleep for I/O, memory allocation and the like. Ordinary mutual exclusion in user-space applications.
Combined
Many mutex implementations combine the strengths of both, taking the lock with atomic instructions alone without sleeping when uncontended, and spinning briefly before sleeping when it cannot be taken.

FAQ

Spinlocks waste CPU time, so why are they used?

Because if the lock is held for a very short time, spinning briefly is faster than paying the context-switch overhead of sleeping and waking. Also, in situations where sleeping is not allowed, such as kernel interrupt handlers, only spinlocks can be used.

Why can't a mutex be used in an interrupt handler?

A mutex puts the waiting thread to sleep when the lock cannot be taken, but an interrupt handler does not run as a particular thread, so it cannot sleep and be woken later. When sharing data with an interrupt handler, use a spinlock combined with disabling interrupts.

What is a futex?

A Linux mechanism for implementing mutexes and similar locks quickly. When there is no contention, it just updates the lock variable with atomic instructions in user space, and only when it must wait due to contention does it make a system call to have the kernel put it to sleep. When most locks are uncontended, it saves system call overhead.

What happens if you use a spinlock on a single-core system?

Even if a thread spins in user space, the lock-holding thread cannot run on that core, so the lock is not freed until the spinning thread uses up its time slice. That is why kernels on single-core systems disable preemption or interrupts for mutual exclusion instead of using spinlocks.

Check your understanding

Which describes a spinlock?

  1. AA lock that puts the thread to sleep until the OS wakes it when the lock is free
  2. BA lock that waits by repeatedly checking the lock variable in a loop until it is free
  3. CA mechanism that protects data by spinning a disk
Show answer and explanation

Answer: B. A lock that waits by repeatedly checking the lock variable in a loop until it is free

A spinlock tries to acquire the lock with an atomic instruction and, if that fails, immediately tries again, over and over. There is no cost of calling the OS to sleep and wake, so it is fast when the lock is held only very briefly. It is common inside OS kernels and for mutual exclusion with interrupt handlers. Its drawback is that it keeps using the CPU while waiting.

In which situation is a spinlock least suitable?

  1. AWhen the lock is held for a long time, so waiting threads waste CPU time spinning
  2. BWhen the lock is held only for tens of nanoseconds
  3. CInside an OS kernel, in code that is not allowed to sleep
Show answer and explanation

Answer: A. When the lock is held for a long time, so waiting threads waste CPU time spinning

A thread waiting on a spinlock keeps using the CPU until the lock is free. If the lock is held for long, all that CPU time is wasted and other threads are held back. On a single core it is worse: the lock cannot be released unless the holder runs, so the waiter spins until its time slice ends. Long waits call for a mutex that sleeps, and some locks spin briefly before sleeping.

Why does a spinlock usually wait with ordinary reads and use an atomic instruction only when the lock looks free (test-and-test-and-set), instead of retrying the atomic write directly?

  1. ABecause ordinary reads are more accurate than atomic instructions
  2. BBecause an atomic instruction may be used only once per program
  3. CReads can wait inside the core's own cache, greatly reducing coherence traffic as the line bounces between cores
Show answer and explanation

Answer: C. Reads can wait inside the core's own cache, greatly reducing coherence traffic as the line bounces between cores

An atomic instruction involves a write, so waiting threads that keep executing it fight to own the line in the M state and keep invalidating others' copies. With ordinary reads, each core just keeps reading its Shared copy in its own cache, generating no traffic. Only when the lock is released and the value changes does a thread try to grab it with an atomic instruction.

  1. Which correctly compares a mutex (a lock that sleeps while waiting) with a spinlock?
  2. Which describes priority inversion in an RTOS?
  3. Which describes priority inheritance, used to prevent priority inversion?

Practice Multicore & Synchronization questions

Key terms explained

Spinlock
A lock that waits by repeatedly checking the lock variable in a loop. Fast for short waits, but it keeps using the CPU while waiting.
Mutex
A lock that only one thread can hold at a time. Typically a thread that cannot get it sleeps and yields the CPU, and the OS wakes it when the lock is released.
Context switch
Switching the process or thread running on a CPU. Registers, the program counter and other state are saved and restored, and switching processes also switches address spaces.
Atomic instruction
An instruction that performs a memory read and write as one operation no other core can interrupt, such as CAS, fetch-and-add and LR/SC.
Priority inversion
A situation in which a high-priority task waiting for a resource held by a low-priority task is held up because a medium-priority task preempts the low one.

Related comparisons