Go Memory Model and Safe Publication
Lesson, slides, and applied problem sets.
View SlidesLesson
Go Memory Model and Safe Publication
This module gives you practical, implementation-oriented confidence in how Go schedules and synchronizes memory between goroutines.
1) What the model promises
The Go memory model answers when one goroutine can observe a write from another.
Core rule:
- If no synchronization edge exists, the compiler and CPU may reorder operations.
- Without happens-before, "working today" can still be nondeterministic.
For concurrency-heavy systems, always define synchronization edges explicitly.
2) Happens-before, in practical terms
- A successful channel send/receive establishes ordering edges.
- A channel close establishes visibility for state before close.
- Mutex unlock happens before next lock release on same mutex.
- Atomic operations also provide ordering guarantees.
Rule in code reviews:
- Never assume assignment + no synchronization = safe cross-goroutine sharing.
3) Safe publication patterns
Safe publication means building complete state before another goroutine can see it.
sync.Mutexguard for mutable struct state.sync.Oncefor one-time init and immutable snapshots.atomic.Pointer[T]where readers must observe only fully formed values.
Pattern (immutable snapshot):
- Build object in local variables.
- Publish via one synchronization event.
- Never mutate after publish.
4) Why immutability matters
If a published object is later mutated, lock-free readers can observe transitional states. This is the most common reason "looks correct in tests" fails in load.
Rule:
- If multiple readers use lock-free publication, state should be write-once.
5) Channels are synchronization boundaries
Channel operations are often enough for correctness:
- closing a channel is a strong signal to multiple readers,
- buffered/unbuffered channels both provide happens-before semantics on successful exchange/close.
Avoid using channels as data races disguised as queues.
6) Atomics are narrow tools
sync/atomic is excellent for counters, flags, and immutable pointer swaps.
- It is not a replacement for lock-based design everywhere.
- It can make lock-free paths faster but also more subtle.
For lock-free publication:
- Store a pointer to an immutable struct.
- Do not mutate that struct after publication.
7) A practical exercise
In this module's practice question, you implement a PublishedCell:
Storepublishes a new immutable snapshot,Loadreads without locking,Swapreturns the previous snapshot.
Success criteria:
- no data races at API level,
- readers always get complete values,
- behavior is deterministic for empty cell cases.
8) Why this lesson comes before the practice problem
The problem is intentionally small:
- it is a concurrency concept that maps directly to production patterns,
- difficult to get right without a mental happens-before model,
- easy to verify with focused tests.
Treat this as your foundation for lock-free cache entries, config hot-reload, and runtime-safe state handoff.