Memory Models & Atomics

the synchronizes-with relation

If happens-before is the chain, synchronizes-with is the single weld that joins two threads' chains together. It is the ONE inter-thread edge in the whole model — the precise moment at which a guarantee crosses from one thread into another. Everything else (sequenced-before) lives inside a single thread; synchronizes-with is the bridge.

The canonical way to create it is the release/acquire pairing: a release operation on an atomic variable synchronizes-with an acquire operation on that SAME variable, provided the acquire actually reads the value that the release wrote (or a later value in that variable's release sequence). When that read happens, an inter-thread edge snaps into place, and by gluing it between the two threads' own sequenced-before orders you get a happens-before path that carries visibility across. Other operations also synchronize-with: unlocking a mutex synchronizes-with the next lock of it; a thread's completion synchronizes-with a successful join() of it; starting a thread synchronizes-with the start of that thread's body.

The two most common bugs are both about the 'reads-the-value' clause. If the acquire reads a DIFFERENT value than the release stored — say a stale value, or a value some third thread wrote — no synchronizes-with edge forms, and you have no happens-before, hence a data race. And a release with no acquire anywhere (or an acquire with no release) is inert: it synchronizes with nothing. Synchronization is a two-party handshake on a shared atomic, not a property you can sprinkle on one side.

store(&ready, 1, release) synchronizes-with load(&ready, acquire) ONLY IF the load returns 1. If the load happens to return 0 (it ran too early), no edge forms — so a retry loop on the acquire is usually what you actually want.

The edge exists only when the acquire reads the released value; reading the old value synchronizes nothing.

Synchronizes-with requires the acquire to OBSERVE the released value — pairing the tags is necessary but not sufficient; if the load reads a stale value the synchronization simply does not happen.

Also called
synchronizes-with同步關係