jonnify·persistence /echo-persistence/mvcc-time-travel/lock-free-readers

Module 5 · Dive 5.2

Lock-free readers.

A reader takes hold of the current root and reads it to the end. Whatever the writer does next — commit a new root, ten new roots — the reader’s view is fixed, because its root is immutable. And the writer never waits for a reader, because it only ever appends. Start a reader, then commit a few times and watch the head pull away while the reader stays put.

§1

The head moves; the reader doesn’t

interactive
Two lanes, one clock. The writer commits versions left to right. Start a reader and it pins to the head of that moment; as the writer commits on, the reader’s bar extends but stays attached to its pinned version.
writer reader time →
readout · Commit a couple of versions, then start a reader. Commit again and watch the head advance while the reader stays pinned to the version it opened on — no lock taken, nothing blocked either way.
§2

Where the locks went

store.design.md

In a mutable store, a reader and a writer touching the same data must take turns, so one waits — that is what a lock is. Immutability removes the shared mutable thing entirely: the reader’s root and the writer’s new root are different objects, so there is nothing to contend over. Readers scale out freely, a long analytical read can’t stall the write path, and the writer’s only serialization is the tiny head swap from Module 3’s OCC, not a lock over the data. For a durable queue this is the difference between “draining the backlog” and “inspecting the backlog” never fighting each other. The one cost is that a reader pins its version alive — which is exactly what GC must respect, in the last dive.

§3

References & sources