Concurrency · 3 MIN READ

A mutex is for state; a channel is for handing over

Choose between a mutex and a channel for a given problem.

A channel is useful for transferring values and coordinating ownership. A mutex protects shared state that remains in place. Choose the mechanism that makes the invariant and its owner easiest to understand; neither mechanism is always faster.

Keep the mutex next to the data it protects and use the same locking rule for every read and write participating in the invariant. A small, clearly bounded critical section is easier to maintain than a lock whose protected state is scattered.

SEE THE IDEA

One lock protects one shared invariant

  1. 01

    Enter

    go
    mu.Lock()

    Wait for exclusive access

  2. 02

    Update

    go
    counter++

    Read and modify the protected state

  3. 03

    Leave

    go
    mu.Unlock()

    Allow the next owner to enter

Every access participating in the shared invariant must follow the same locking rule.

In practice

Keep the critical section short and make lock ownership easy to see. A deferred unlock protects early returns, while an explicit unlock may be clearer around a small block. Use a channel when transferring ownership expresses the operation better than protecting shared mutable state.

Watch out

Protect reads as well as writes. Copying a used mutex or taking the same mutex twice can break the synchronization contract.

Official reference ↗

Work through the exercise

go
package main

import "sync"

// Counter should be safe for many goroutines at once.
type Counter struct {
	mu    sync.Mutex
	count map[string]int
}

func NewCounter() *Counter {
	return nil
}

func (c *Counter) Add(key string) {}

func (c *Counter) Get(key string) int { return 0 }

func main() {}
Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.