Go Memory Model and Safe Publication

Lesson, slides, and applied problem sets.

View Slides

Lesson

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.Mutex guard for mutable struct state.
  • sync.Once for one-time init and immutable snapshots.
  • atomic.Pointer[T] where readers must observe only fully formed values.

Pattern (immutable snapshot):

  1. Build object in local variables.
  2. Publish via one synchronization event.
  3. 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:

  • Store publishes a new immutable snapshot,
  • Load reads without locking,
  • Swap returns 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.


Module Items

Join Discord