Problem Statement
A Staff Engineer at Stripe asks: "We have a high-frequency payment counter that increments millions of times per second. Should we use a Mutex, Channels, or Atomics? Explain your reasoning and benchmark the difference."
The Go Proverb
"Share memory by communicating, don't communicate by sharing memory."
But this doesn't mean channels are always the right choice.
Decision Framework
| Use Case | Best Choice | Reason |
|---|---|---|
| Simple counter | atomic.AddInt64 | Hardware instruction, fastest |
| Protecting complex state | sync.Mutex | Clear ownership semantics |
| Coordinating goroutines | Channels | Communication pattern |
| Read-heavy, write-rare | sync.RWMutex | Multiple concurrent readers |
Benchmark Implementation
Typical Results
Conclusion
For the payment counter scenario: Use atomic operations. They're ~4x faster than Mutex and ~18x faster than channels for simple increments.
Follow-up Questions
- When would channels be the better choice despite being slower?
- What is "False Sharing" and how does it affect atomic counters?
- How do you implement a lock-free data structure?