Spinning Until the Lock Gives
Work-hardening gives no warning. The bronze wire just… snaps. Six draws through progressively smaller holes in the jeweller’s plate, and somewhere between the fifth and sixth, the metal decides it’s had enough. No change in resistance, no sound, no flex. The material commits silently to failure.
Spin-waiting has the same silence. A thread loops, checking a flag, checking again, checking a thousand more times:
#!/bin/bash
LOCK=/tmp/spinlock
acquire() {
while ! mkdir "$LOCK" 2>/dev/null; do
: # spin
done
}
release() { rmdir "$LOCK"; }
acquire
echo "critical section"
release
mkdir is atomic on POSIX systems — it either succeeds (you got the lock) or fails (someone else holds it). The colon in the loop body is a no-op. The thread burns cycles doing nothing visible, waiting for permission that might never arrive.
Elixir avoids spinlocks by design — message-passing means no shared memory to fight over — but you can still model the pattern to understand why it’s usually wrong:
defmodule Spin do
def wait_for(flag_fn, action) do
if flag_fn.() do
action.()
else
wait_for(flag_fn, action) # tail recursion, still spinning
end
end
end
Spin.wait_for(fn -> File.exists?("/tmp/ready") end, fn ->
IO.puts("flag appeared")
end)
This polls the filesystem endlessly until /tmp/ready materializes. Unlike the bash version, BEAM’s scheduler will yield between iterations, so you won’t starve other processes. But you’re still spending energy on observation rather than work.
The 1980s brought symmetric multiprocessing to non-mainframe hardware, and suddenly programmers needed primitives for multiple CPUs accessing shared structures. Spinlocks emerged as the simplest option: no kernel involvement, no context switches, just atomic test-and-set in a loop. On machines where lock contention was brief and cores were few, spinning cost less than sleeping.
But the failure mode is invisible. A thread holding the lock crashes, and every waiter spins forever. No timeout, no escalation, no sound of metal giving way. The process looks alive — CPU at 100% — while accomplishing nothing.
Annealing would help the bronze. Periodic heating resets the crystal structure, erasing the accumulated stress. Spinlocks with backoff do something similar: after N failed attempts, sleep briefly, reset the tension, try again. The material gets to recover between draws. The thread gets to do other work between checks.
Without backoff, both processes end the same way: committed past the point of return, producing heat and nothing else.