Go语言中用sync/atomic做高并发计数的核心优势是快、轻、安全——不加锁,靠CPU指令原生保证操作不可分割,避免锁竞争与协程阻塞,内存可见性自动保障,语义简洁不易出错,适用于高频单值简单变更场景。

Go语言中用sync/atomic做高并发计数,核心优势是快、轻、安全——不加锁,靠CPU指令原生保证操作不可分割。
避免锁竞争与协程阻塞
传统sync.Mutex保护计数器时,每次counter++都要抢锁、等锁、释放锁。上千goroutine同时争抢,会触发大量上下文切换和排队等待,性能急剧下降。而atomic.AddInt64直接调用底层LOCK XADD(x86)或LDXR/STXR(ARM)等原子指令,无锁、无调度、无阻塞。
- 没有goroutine被挂起或唤醒,节省调度开销
- 不会因锁持有时间长引发“锁拖尾”问题
- 在百万级QPS的请求统计场景下,吞吐量通常比mutex高3–10倍
内存可见性自动保障
原子操作自带内存屏障(memory barrier),能确保写入立即对其他goroutine可见,无需额外同步手段。
-
atomic.StoreInt64写入后,其他goroutine调用atomic.LoadInt64一定能读到最新值 - 不会出现“缓存未刷新”导致的脏读(这是普通变量+
go run -race常报data race的原因) - 比手动加
runtime.Gosched()或sync/atomic外绕道更可靠
语义简洁,不易出错
计数逻辑只涉及单个整型变量时,原子操作API直白明确,没有忘记Unlock、死锁、panic等风险。
立即学习“go语言免费学习笔记(深入)”;
-
atomic.AddInt64(&c, 1)一行完成“读-改-写”,无中间态暴露 - 不需要定义结构体、封装方法、管理锁生命周期
- 配合
sync.WaitGroup就能写出可验证的正确并发计数器
适用边界清晰,不滥用也不妥协
它不是万能锁替代品,但恰恰卡在“高频、单值、简单变更”的黄金场景。
- 适合:请求总数、错误次数、活跃连接数、限流令牌剩余量
- 不适合:需同时更新多个字段(如用户余额+流水号)、带条件逻辑(如“余额>100才扣款”)——这类必须用
sync.Mutex或CAS重试 - 注意:32位系统上
int64必须内存对齐(建议放结构体首字段),否则可能panic


















