Table of Contents
Spinlock
A spinlock is a Lock where a thread that fails to acquire it busy-waits, repeatedly retrying in a tight loop, instead of yielding the core back to the OS scheduler. There is no context switch involved in either acquiring or waiting, which makes a spinlock cheap to enter when the critical section is short, at the cost of burning CPU cycles the whole time another thread is waiting.
#include <stdatomic.h> atomic_flag lock = ATOMIC_FLAG_INIT; void spin_lock(void) { while (atomic_flag_test_and_set_explicit(&lock, memory_order_acquire)) { /* spin */ } } void spin_unlock(void) { atomic_flag_clear_explicit(&lock, memory_order_release); }
When spinning is the right call
Spinning only pays off when the expected wait is shorter than the cost of two context switches (putting the waiting thread to sleep, then later waking it back up). This is common inside kernels and low-level runtimes, where critical sections are deliberately kept to a handful of instructions specifically so a spinlock is viable. It is a bad fit for user-space code with long or unpredictable critical sections, where a blocking mutex wastes far less CPU under contention.
Test-and-test-and-set
A naive spinlock retries test_and_set on every iteration, which means every failed attempt still issues a bus-level atomic operation and generates coherence traffic even when the lock is obviously still held. The test-and-test-and-set variant fixes this by spinning on a plain (non-atomic) load first, only attempting the actual test_and_set once that load suggests the lock might be free:
void spin_lock_ttas(void) { for (;;) { while (atomic_load_explicit(&lock_flag, memory_order_relaxed)) { /* spin on a cheap local load, no bus traffic while contended */ } if (!atomic_exchange_explicit(&lock_flag, 1, memory_order_acquire)) { return; // actually acquired } } }
Because a plain load can be satisfied from the local core's cache without any bus transaction (as long as no one else is writing), this keeps a contended spinlock from flooding the interconnect with coherence traffic, which is exactly the failure mode a naive spinlock falls into under high contention: many cores fighting over the same cache line via Cache coherence traffic rather than the actual critical section.
