Go Benchmark
Channel vs Mutex
Sharing a value by communicating vs communicating by sharing.
"Don't communicate by sharing memory; share memory by communicating" is Go's most famous proverb — but channels are not free. This benchmark moves an int64 between two points using a buffered channel (send + receive) and compares it against a mutex-guarded variable (locked write + locked read), so both variants pay exactly two synchronization points per operation. The "Serial" tab shows the uncontended baseline cost of each primitive; the "Parallel" tab shows what happens under contention from multiple goroutines. Channels buy you ownership transfer, select, and cancellation semantics — this chart shows what that abstraction costs when all you need is to protect a value.
1 CPU
32 CPUs
Writes the value into a shared variable under a sync.Mutex, then reads it back under the same lock. In the uncontended fast path, lock and unlock are each a single atomic operation with no allocations, making this the cheapest way to protect plain shared state when you don't need channel semantics.
Sends the value into a chan int64 with buffer size 1 and receives it back. Every send and receive goes through the runtime's channel machinery: an internal mutex, copying the element, and potentially parking/waking goroutines under contention. That machinery is what enables select, timeouts, and clean handoff semantics.
Contributors