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
gostatement 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
Unlockhappens-before the m-thLockreturns, for n < m. - The completion of
finonce.Do(f)happens-before anyDoreturns. - 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
- Q230What are typed atomics (atomic.Int64, atomic.Pointer[T]) and why prefer them over atomic.AddInt64 / atomic.Value?
- Q231Implement a lock-free "store max" using compare-and-swap. What is the ABA problem, and does it affect Go?
- Q233What does this program print?
- Q234How does the race detector work, and what are its limitations? Is a "benign" data race ever OK?
- Q235Does this counter give the right answer with GOMAXPROCS=1? What about counter++ in general?
- Q236What does this print in Go 1.22+ vs before?