livelock — livelock — run at full effort and arrive nowhere
livelock [--after-you]... [--politeness=FLOAT] [--no-jitter] PARTIES
while (both_yield) { yield() }
busy == true, progress == 0
livelock places two or more parties in continuous, mutually reactive motion. Each observes the other, defers, adjusts, and retries. Every thread stays runnable and its state changes on every tick. The single quantity that never changes is progress.
It is not deadlock(8). Deadlock blocks: the threads are parked, the CPU is idle, and a scheduler can at least see that nothing is happening. livelock keeps everyone pinned at 100 percent — yielding, backing off, and re-acquiring in lockstep — so the machine reports as fully utilized and remains fully useless. It is starvation with excellent posture.
Termination requires that the symmetry be broken exactly once: a random delay, a timeout, or a single party that declines to be accommodating. Absent that, livelock runs until the power does.
The word is a play on deadlock, substituting live to mark that the processes never actually stop: they stay in the run or ready state, which makes livelock a species of starvation rather than of blocking. Its most cited treatment is Jeffrey Mogul and K. K. Ramakrishnan's "Eliminating Receive Livelock in an Interrupt-Driven Kernel" (USENIX 1996; ACM TOCS 1997), which described network kernels spending the entire CPU servicing interrupts while delivering zero packets to applications. The standard remedies — randomized backoff, timeouts, and priority asymmetry — all work by guaranteeing that the contending parties stop behaving identically.
--break-symmetry works as documented. It is almost never passed. The parties consider it rude.
Two operators racing to resolve a livelock by hand reliably reproduce the livelock they are resolving.
Not to be confused with deadlock(8), which at least has the decency to stop.
thrashing(8), backpressure(3), quiescence(1). The living exhibit demonstrates the word in motion:
▸ operate livelock