2026-06-27
A regular mutex treats every thread the same: one in, everyone else waits. That's wasteful when 95% of your traffic is reads. A read-write lock (RWLock) distinguishes between shared access (many readers at once) and exclusive access (one writer, no readers). Readers don't block readers. Writers block everyone.
The mental model: think of a whiteboard in a meeting room. Any number of people can read it simultaneously. But if someone needs to erase and rewrite, everyone else has to step back until they're done.
Concrete example — a routing table in an API gateway. Every request reads the route map to find the upstream service. Routes change maybe once per minute when a deploy lands. With a plain mutex, 50,000 reads/sec serialize through a single critical section. Swap to an RWLock and reads run concurrently; the once-a-minute writer briefly blocks them. Throughput jumps from "limited by lock contention" to "limited by CPU."
The rule of thumb: RWLocks win when reads outnumber writes by at least 10:1 and the critical section is non-trivial (more than a pointer swap). Below that ratio, the extra bookkeeping (tracking reader counts, signaling writers) costs more than a plain mutex. For tiny critical sections, an atomic or a plain mutex usually beats an RWLock.
The traps:
sync.RWMutex, Java's ReentrantReadWriteLock in fair mode) block new readers once a writer is queued. Verify your implementation's policy — don't assume.The alternative worth knowing: a copy-on-write snapshot. Writers replace an immutable pointer atomically; readers grab the pointer with zero synchronization. Great for write-rare data like config and routing tables. The cost is full-structure allocation per write — fine at one write/minute, terrible at one write/second.
Choose by read:write ratio and critical-section size, not by reflex.
