news 2026/6/3 10:11:35

atomic 原子操作到底有多快?我拿 Mutex 做了个对比测试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
atomic 原子操作到底有多快?我拿 Mutex 做了个对比测试

atomic 原子操作到底有多快?我拿 Mutex 做了个对比测试

前言

写并发代码,锁是免不了的。Mutex 好用,但确实慢。高并发场景,atomic 原子操作是个好东西,但很多人不知道怎么用对。

今天我拿两百万次并发操作做了个测试,结果真的差很远。

一、底层原理

1.1 atomic 到底是怎么工作的

atomic 原子操作利用 CPU 指令级别的支持,确保内存操作的原子性:

graph TD A["多个协程同时写"] --> B["CPU 内存总线"] B --> C["Mutex: 操作系统锁"] B --> D["Atomic: CPU 指令锁"] C --> E["用户态/内核态切换"] D --> F["硬件级别保证"] E --> G["耗时: 微秒级"] F --> H["耗时: 纳秒级"]

关键点:

  • Mutex 涉及系统调用,昂贵
  • atomic 直接调用 CPU 指令
  • atomic 不会阻塞协程调度
  • 从 GMP 角度看,atomic 不影响 P 的运行队列

1.2 atomic vs Mutex 对比

维度atomicMutex差距
速度纳秒级微秒级100倍
协程阻塞不阻塞阻塞显著
适用场景简单计数器复杂临界区-
使用难度-

二、快速上手

直接看代码对比:

package main import ( "fmt" "sync" "sync/atomic" "time" ) var ( mutexCount int64 atomicCount int64 mu sync.Mutex ) func testMutex(wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 100000; i++ { mu.Lock() mutexCount++ mu.Unlock() } } func testAtomic(wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 100000; i++ { atomic.AddInt64(&atomicCount, 1) } } func main() { var wg sync.WaitGroup n := 100 start := time.Now() for i := 0; i < n; i++ { wg.Add(1) go testMutex(&wg) } wg.Wait() fmt.Printf("Mutex: %v, count: %d\n", time.Since(start), mutexCount) atomicCount = 0 start = time.Now() for i := 0; i < n; i++ { wg.Add(1) go testAtomic(&wg) } wg.Wait() fmt.Printf("Atomic: %v, count: %d\n", time.Since(start), atomicCount) }

在我的机器上跑,atomic 快了至少 10 倍。

三、核心 API / 深水区

3.1 atomic 操作速查

函数功能注意事项
AddInt64原子加对齐要求
LoadInt64原子读防止乱序
StoreInt64原子写防止乱序
CompareAndSwapCAS乐观锁
Swap交换返回旧值

3.2 原子操作必须对齐

这个在内存对齐那篇说过,这里再强调一次:

type BadCounter struct { flag byte count int64 // 没对齐! } type GoodCounter struct { count int64 // 对齐了 flag byte }

3.3 CAS 乐观锁原理

CAS 是 Compare And Swap,先比较再替换:

var value int64 func update(newValue int64) { for { old := atomic.LoadInt64(&value) if atomic.CompareAndSwapInt64(&value, old, newValue) { return } // 失败就重试 } }

四、实战演练

用 atomic 实现高性能计数器:

package main import ( "fmt" "sync" "sync/atomic" "time" ) type AtomicCounter struct { count int64 } func (c *AtomicCounter) Inc() { atomic.AddInt64(&c.count, 1) } func (c *AtomicCounter) Dec() { atomic.AddInt64(&c.count, -1) } func (c *AtomicCounter) Value() int64 { return atomic.LoadInt64(&c.count) } type MutexCounter struct { mu sync.Mutex count int64 } func (c *MutexCounter) Inc() { c.mu.Lock() c.count++ c.mu.Unlock() } func (c *MutexCounter) Dec() { c.mu.Lock() c.count-- c.mu.Unlock() } func (c *MutexCounter) Value() int64 { c.mu.Lock() defer c.mu.Unlock() return c.count } func main() { var wg sync.WaitGroup ac := &AtomicCounter{} mc := &MutexCounter{} start := time.Now() for i := 0; i < 50; i++ { wg.Add(1) go func() { defer wg.Done() for j := 0; j < 200000; j++ { ac.Inc() } }() } wg.Wait() fmt.Printf("Atomic: %v, value: %d\n", time.Since(start), ac.Value()) start = time.Now() for i := 0; i < 50; i++ { wg.Add(1) go func() { defer wg.Done() for j := 0; j < 200000; j++ { mc.Inc() } }() } wg.Wait() fmt.Printf("Mutex: %v, value: %d\n", time.Since(start), mc.Value()) }

五、避坑指南与最佳实践

💡 **技巧:读也加 Load 不是白加的
不加 Load 可能读到旧值,因为 CPU 乱序执行。

⚠️ **警告:atomic 不能替代 Mutex
复杂的临界区,还得上 Mutex。

✅ **推荐:简单计数器用 atomic
高频场景,atomic 是你的朋友。

六、综合实战演示

生产级并发限流器:

package main import ( "fmt" "sync" "sync/atomic" "time" ) type RateLimiter struct { limit int64 current int64 interval time.Duration lastTime time.Time } func NewRateLimiter(limit int64, interval time.Duration) *RateLimiter { return &RateLimiter{ limit: limit, interval: interval, lastTime: time.Now(), } } func (rl *RateLimiter) Allow() bool { now := time.Now() if now.Sub(rl.lastTime) >= rl.interval { atomic.StoreInt64(&rl.current, 0) rl.lastTime = now } current := atomic.AddInt64(&rl.current, 1) return current <= rl.limit } func main() { rl := NewRateLimiter(100, time.Second) var wg sync.WaitGroup passed := int64(0) blocked := int64(0) for i := 0; i < 200; i++ { wg.Add(1) go func() { defer wg.Done() if rl.Allow() { atomic.AddInt64(&passed, 1) } else { atomic.AddInt64(&blocked, 1) } }() } wg.Wait() fmt.Printf("通过: %d, 阻塞: %d\n", passed, blocked) }

七、总结

atomic 和 Mutex 各有各的用法:

  • 简单计数用 atomic
  • 复杂临界区用 Mutex
  • atomic 快但不万能
  • 注意内存对齐

选对工具,性能翻倍。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/3 10:10:41

后摩尔时代:从晶体管微缩到异构集成与架构创新的算力演进

1. 摩尔定律的“终局”与“重生”&#xff1a;一个老生常谈的行业迷思“摩尔定律又双叒叕要终结了”——如果你在半导体行业待得够久&#xff0c;或者稍微关注点科技新闻&#xff0c;这句话大概每隔三五年就会像季节更替一样准时出现。从90纳米工艺的“物理极限”警告&#xff…

作者头像 李华
网站建设 2026/6/3 10:10:18

免费图片去水印工具全场景实操指南,适配手机电脑多设备日常素材处理

在日常素材整理、自媒体内容制作、个人图片留存的过程中&#xff0c;图片水印是高频困扰问题。多余的平台logo、文字水印、边角标识会影响图片观感与使用效果。2026年市面主流的免费图片去水印工具分为网页在线、电脑客户端、手机APP、微信小程序四大品类&#xff0c;不同品类适…

作者头像 李华
网站建设 2026/6/3 10:08:05

云计算与大数据在农业气候风险评估中的应用实践

1. 项目概述&#xff1a;当大数据遇见农业&#xff0c;我们如何预判餐桌的未来&#xff1f;气候变化对粮食供应的影响&#xff0c;这绝对不是一个可以轻松回答的问题。它不像预测明天的天气&#xff0c;或者估算一块地的收成那么简单。这是一个交织着气象学、农学、生态学、经济…

作者头像 李华
网站建设 2026/6/3 10:07:25

如何高效解锁原神60FPS限制:完整配置与性能优化指南

如何高效解锁原神60FPS限制&#xff1a;完整配置与性能优化指南 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 原神作为一款画面精美的开放世界游戏&#xff0c;其默认的60FPS帧率限制已…

作者头像 李华