Mutex 是互斥锁,任何时刻只有一个持有者,读写都排他。RWMutex 区分读写:读锁可并发共享,写锁独占并阻塞后续读写,理论上适合'读多写少'。
但选择依据不是'读多就用 RWMutex'这么简单。RWMutex 内部要维护读者计数和写者等待状态,单次操作成本高于 Mutex;临界区极短(几行内存读写)时,即使读多写少,Mutex 往往更快。只有临界区较耗时(遍历大 map、拷贝数据)且读远多于写,RWMutex 才有收益。写较多的场景 RWMutex 反而更差,写锁获取路径更重。
type Cache struct {
mu sync.RWMutex
m map[string]string
}
func (c *Cache) Get(k string) (string, bool) {
c.mu.RLock(); defer c.mu.RUnlock()
v, ok := c.m[k]; return v, ok
}
易错点:读锁内不能再获取写锁(Go 的 RWMutex 不支持锁升级,会死锁);锁不可拷贝,含锁结构体禁止值传递(go vet 会报 copies lock);读多写少且可快照的数据可考虑 atomic.Value。追问方向:Mutex 的饥饿模式、sync.Map 的适用边界。