A spinlock is a mutex whose waiting thread repeatedly tries to acquire it instead of making a blocking call. A simple C++ implementation uses an initially clear std::atomic_flag: lock() loops on test_and_set() until it returns false, meaning the caller has set the flag and acquired the lock. unlock() clears it. section 5.2.2 section 7.1.1
Listing 5.1. Implementation of a spinlock mutex using std::atomic_flag
class spinlock_mutex
{
std::atomic_flag flag;
public:
spinlock_mutex():
flag(ATOMIC_FLAG_INIT)
{}
void lock()
{
while(flag.test_and_set(std::memory_order_acquire));
}
void unlock()
{
flag.clear(std::memory_order_release);
}
};
The loop keeps trying while the flag was already set. The first caller to observe a clear flag exits the loop; its unlock() clears the flag for a later caller. section 5.2.2
The acquire ordering on a successful test_and_set() pairs with the release ordering on clear(). Changes to protected data made before unlock() happen before accesses by a thread that subsequently acquires the lock. This is why the loop provides more than exclusive entry: it also orders access to the data it protects. section 5.3.7
Busy-waiting makes this basic mutex a poor choice when contention is expected. Although lock() makes no blocking call, the design is not lock-free: a thread holding the mutex can prevent another thread from completing. A barrier can also use a spinning wait, yielding while it checks for a generation change; that simple approach is unsuitable for long waits. section 5.2.2 section 7.1.1 section 8.5.3

