Skip to content

Day 070 — Week 2 Review Day

Month 3 · Week 2 · ⬅ Day 069 · Day 071 ➡ · Journal index

📋 Full structured review: week-2-review.md

🎯 Learning Objective

Consolidate Week 2 of concurrency (the sync toolbox + the memory model) via closed-book recall and re-run every example and exercise under the race detector.

📚 Topics

  • Recap: sync.Mutex/RWMutex, WaitGroup in depth, sync.Once & sync.Pool, sync/atomic + CAS, the -race detector, the Go memory model & happens-before.

📝 Notes

  • Re-ran each example (go run ./examples/month-03/{mutex,waitgroup,once-pool,atomic}) and go test -race ./exercises/month-03/week-2/... — safecounter, oncecache, atomicgate all green, no races.
  • Ran gofmt -l . and go vet ./... — no copied locks/atomics, no Printf issues.
  • Reimplemented the CAS storeMax loop and the once-per-key cache from memory (active recall); got the LoadOrStore + per-key Once pairing right on the second try.

🧠 Closed-Book Recall (Week 2)

  1. Q: When RWMutex over Mutex?
    A

When reads vastly outnumber writes — many RLock holders run concurrently; otherwise the bookkeeping can make it slower than a plain Mutex. 2. Q: Why Add before go?

A

Add inside the goroutine races with Wait, which may see a zero counter and return early.

3. Q: Does once.Do(f) retry if f panics?
A

No — the call is consumed; f never runs again. Once is wrong for retry-on-failure init.

4. Q: Why copy data out of a pooled buffer before Put?
A

After Put, another goroutine can Get+Reset it and overwrite the backing array, corrupting any view you still hold.

5. Q: What does CompareAndSwap(old,new) return and how is it used?
A

true if it set new (current still equalled old), else false; loop and retry on false for lock-free updates.

6. Q: Is a clean go test -race a proof of race-freedom?
A

No — it's a dynamic detector; it only flags races that actually occurred this run.

7. Q: A data race is "a stale read" — true?
A

False — it's undefined behaviour; the program has no guaranteed semantics. Add a happens-before edge.

🐛 Mistakes / Themes This Week

  • Copied a struct holding a Mutex/atomic → go vet "copies lock value" (Days 064, 067).
  • Returned a pooled buffer's Bytes() after Put (Day 066).
  • Used a plain bool flag to publish data across goroutines — no happens-before edge (Day 069).

🪶 Feynman Reflection

I now have the second half of the concurrency toolbox: when sharing memory in place beats passing it over a channel, guard it — a Mutex/RWMutex for multi-field state, an atomic for a single counter/flag, Once for run-once init, Pool for recycling, all underwritten by the memory model's happens-before edges and verified with -race.

🕳️ Knowledge Gaps Carried Forward

  • context.Context for cancellation/deadlines (next week).
  • Mutex/CAS contention profiling and the crossover where each wins (optimisation month).

✅ Summary

Week 2 sync primitives + memory model consolidated; all examples and exercises formatted, vetted, and -race-clean. Confidence on mutex/atomic/once now 3–⅘.

⏭️ Next Steps

  • Week 3: context.Context — cancellation, deadlines, WithTimeout/WithCancel, and propagation through call chains.

Time spent Difficulty Confidence
75 min 🟦⬜⬜⬜⬜ 🟦🟦🟦🟦⬜

Suggested commit: docs(journal): month 3 week 2 review (day 070)