原子变量适用于整型计数器、布尔标志位、指针/uintptr地址切换、无符号版本号等单次操作语义明确的轻量状态;不适用于多字段结构体更新,后者需sync.rwmutex或atomic.value。

直接用原子变量替代普通变量读写,能绕过锁的调度开销,在高频读写全局状态时显著提速。关键不是“快一点”,而是避免 goroutine 阻塞和上下文切换,尤其适合计数、开关、版本号这类轻量状态。
哪些状态适合用原子变量
只适用于结构简单、单次操作语义明确的值:
- 整型计数器(如请求总数、活跃连接数)
- 布尔标志位(如 isRunning、isReady)
- 指针或 uintptr 类型的地址切换(如配置对象引用)
- 无符号整数版本号或序列号(如 atomic.Uint64)
不适用于字段多、需多步更新的结构体——那种情况仍得靠 sync.RWMutex 或 atomic.Value 封装。
常用操作怎么写才安全
别直接赋值或自增,必须调用 sync/atomic 提供的函数:
- 递增:用 atomic.AddInt64(&counter, 1),不是 counter++
- 读取:用 atomic.LoadInt64(&counter),保证看到最新值
- 写入:用 atomic.StoreInt64(&flag, 1),而非 flag = 1
- 条件更新:用 atomic.CompareAndSwapInt32(&state, 0, 1) 实现状态跃迁
所有操作都带内存屏障语义,自动处理可见性与重排序问题,无需手动加 sync。
注意对齐和类型匹配
在 32 位系统或某些结构体中,int64 若未自然对齐会 panic。稳妥做法:
- 把原子变量单独声明为包级变量(Go 自动对齐)
- 或放在结构体第一个字段(如 type State struct { count int64; name string })
- 复杂类型(如 map、struct)改用 atomic.Value,先 Store 指针,再 Load 转换
别把它当万能锁用
原子操作不是互斥锁的平替:
- 不能保护多个变量的联合更新(比如同时改 count 和 lastTime)
- CAS 循环重试在高冲突场景下可能浪费 CPU
- 没有阻塞等待能力,不适合需要“等某个条件成立”的逻辑
该上 sync.Mutex 还得上,原子变量只负责“单点快照”和“单步变更”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











