Go

When would you use sync.RWMutex over sync.Mutex, and when can RWMutex actually be slower?

Question 221MediumGo 1.22 to 1.25

RWMutex allows many concurrent readers or one writer. It pays off only when reads heavily outnumber writes and the critical section is long enough that letting readers run in parallel matters.

It can be slower than a plain Mutex because:

  • RLock/RUnlock atomically update a shared reader counter. On many cores that cache line bounces between CPUs, so tiny critical sections scale worse than with a Mutex.
  • It has more bookkeeping (reader count, writer wait, two semaphores).
  • Writers get priority: once a writer calls Lock, new RLock calls block until the writer has finished. With frequent writes you get little read parallelism.
type Config struct {
	mu   sync.RWMutex
	vals map[string]string
}

func (c *Config) Get(k string) (string, bool) {
	c.mu.RLock()
	defer c.mu.RUnlock()
	v, ok := c.vals[k]
	return v, ok
}

func (c *Config) Set(k, v string) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.vals[k] = v
}

What the interviewer is looking for: you benchmark before choosing (go test -bench -cpu=1,4,16). For read-mostly data that is replaced as a whole, atomic.Pointer[T] with copy-on-write usually beats both locks.

More on Concurrency Patterns & sync

All 38 Concurrency Patterns & sync questions