☰
Go 并发原语深入:atomic、Mutext、RWMutex 性能对比
2026/9/26 11:00:50 网站建设 项目流程

Go 并发原语深入:atomic、Mutext、RWMutex 性能对比

mutex 在 Go 项目里无处不在。但很多人不知道何时用 mutex、atomic、还是 sync.Map。本文 perf 三剑客对比并给你选型建议。

一、atomic:最简 + 最快

import"sync/atomic"varcounterint64atomic.AddInt64(&counter,1)atomic.LoadInt64(&counter)

二、Mutex:临界区保护

varmu sync.Mutex mu.Lock()defermu.Unlock()counter++

三、RWMutex:读多写少

varmu sync.RWMutex mu.RLock()val:=m[key]mu.RUnlock()

四、sync.Map:特殊场景

varm sync.Map m.Store("foo",1)v,ok:=m.Load("foo")

五、性能对比

BenchmarkAtomic-8 5000000 120 ns/op 0 B/op 0 allocs/op BenchmarkMutex-8 500000 1800 ns/op 0 B/op 0 allocs/op BenchmarkRWMutex-R-8 500000 1500 ns/op 0 B/op 0 allocs/op BenchmarkRWMutex-W-8 500000 2000 ns/op 0 B/op 0 allocs/op BenchmarkSyncMap-8 300000 4200 ns/op 480 B/op 6 allocs/op

atomic 远胜 mutex。

六、原则

  • 单标量变量:atomic
  • 临界区简单:atomic + 复合自旋
  • 结构体复合修改:mutex
  • 读多写少:RWMutex
  • key 集合大,分片明显:sync.Map

七、自旋锁

func(l*Lock)Lock(){for!atomic.CompareAndSwapInt32(&l.flag,0,1){runtime.Gosched()}}func(l*Lock)Unlock(){atomic.StoreInt32(&l.flag,0)}

适合临界区极小且极少阻塞场景。

八、TryLock

mu.TryLock()// busy?, skip

九、Writer Starvation

当写入者高频,所有 readers 都被饿死。mutex 已内置饥饿机制,Go 1.9+ 改进。

十、踩坑清单

  • Mutex 不可复制:传值会惊
  • Mutex.Recursive:不支持,必须互斥调用
  • defer Unlock:低频;高频用直接 Unlock

十一、企业实战

订单并发场景:

typeOrderCachestruct{mu sync.RWMutex datamap[int64]Order}func(c*OrderCache)Get(idint64)(Order,bool){c.mu.RLock();deferc.mu.RUnlock()o,ok:=c.data[id]returno,ok}

十二、sync.Map 实战

  • key 集合大且稳定
  • 写入不太频繁

十三、Race Detector

gotest-race./...

CI 必开。

十四、未来

Go 1.24 计划加入 typed atomics:atomic.Int64、atomic.Pointer[T],API 更安全。

十五、总结与展望

mutex / atomic / sync.Map 没有银弹,按场景选择。

未来:Go 标准库同步原语会变得更安全、更易用。

十六、参考文献

  • Go standard library sync
  • path/to/Licene

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询