2026-06-20
Most reader-writer locks penalize readers: they take a lock, touch a shared cache line, and serialize against other readers on the bus. For data that's read constantly but written rarely — system time, configuration, routing tables — that's a brutal tax. The seqlock (sequence lock) flips the deal: readers pay nothing on the fast path, and writers eat the cost.
The mechanism is a single monotonically increasing counter plus the protected data:
Readers never write to shared memory. No cache line bouncing, no atomic RMW, no contention between readers. The two counter reads bracket the data read like a tripwire: if a writer touched anything in between, the reader sees a mismatch and retries.
Real-world example: the Linux kernel uses seqlocks for jiffies and gettimeofday(). Millions of cores call gettimeofday() per second; the timekeeping code updates the clock source maybe 1000 times per second. With a mutex, every reader would serialize on a single cache line — catastrophic. With a seqlock, readers run in parallel and the timer interrupt handler is the only writer.
Rule of thumb: seqlocks win when the read:write ratio exceeds roughly 100:1 AND the protected data is small enough to read in a handful of instructions. If reads are long, retry probability under contention rises as P(retry) ≈ read_duration / write_interval, and you can livelock.
The non-obvious traps:
Use seqlocks for scalar snapshots: clocks, counters, small config structs. Reach for RCU when readers walk pointers. Reach for a mutex when writes are frequent or reads are slow.
