Go

Explain the Go memory model and "happens-before". What synchronization edges does Go guarantee?

Question 232HardGo 1.22 to 1.25

The memory model says when a read in one goroutine is guaranteed to see a write made in another. If a write happens-before a read and no other write intervenes, the read sees it. Without a happens-before edge there is no guarantee, and the compiler and CPU may reorder operations.

Go promises DRF-SC: a data-race-free program behaves as if it were sequentially consistent. Racy programs have limited but real undefined behavior. Multiword values such as interfaces, slices and strings can tear, which can cause crashes.

The key edges:

  • A go statement happens-before the new goroutine starts. Goroutine exit has no edge.
  • A send on a channel happens-before the corresponding receive completes.
  • close(ch) happens-before a receive that returns because the channel is closed.
  • A receive on an unbuffered channel happens-before the matching send completes.
  • The k-th receive on a channel with capacity C happens-before the (k+C)-th send completes. This is what makes a buffered channel work as a semaphore.
  • For a mutex, the n-th Unlock happens-before the m-th Lock returns, for n < m.
  • The completion of f in once.Do(f) happens-before any Do returns.
  • Atomics (since the Go 1.19 formalization) behave like sequentially consistent atomics. If B observes A's atomic write, A happens-before B.

What the interviewer is looking for: you can explain why a busy-wait on a plain bool is broken (see the next question), and you know that time.Sleep is never a synchronization mechanism.

More on Concurrency Patterns & sync

All 38 Concurrency Patterns & sync questions