Stage 3 · Build
Concurrency in Depth
sync Primitives
Mutex, RWMutex, Cond, Once, Pool, atomic, and when channels are the wrong tool.
sync.Mutex
Mutex protects shared state from concurrent access. Lock before accessing shared data, unlock after. Use defer for unlock to prevent forgotten unlocks.
sync.RWMutex
RWMutex allows multiple concurrent readers or one exclusive writer. Use it when reads are frequent and writes are rare.
sync.Once
Once ensures a function is executed exactly once, even across multiple goroutines. It is used for lazy initialization of singletons, configuration loading, and connection setup.
sync.Pool
Pool is a temporary object cache. It reduces garbage collection pressure by reusing objects. Each P (processor) has a private pool and a shared pool.
atomic Operations
atomic operations provide lock-free synchronization for simple types. They are faster than mutex for single-value updates: counters, flags, and pointers.
Channels vs sync
Channels and mutexes serve different purposes. Choose based on the problem, not habit.
| Use Channels When | Use sync When |
|---|---|
| Communicating data between goroutines | Protecting shared state |
| Coordinating goroutine lifecycle | Simple counters and flags |
| Implementing pipelines | Read-heavy concurrent access |
| Signaling events | Single-process in-memory state |
Mutexes are simpler to reason about. Start with a mutex for shared state. If you find yourself passing data between goroutines, switch to channels. Do not prematurely optimize with atomic operations unless profiling shows a bottleneck.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.