atomic.addint64是并发安全自增唯一方式,因++非原子易致data race;必须用int64且对齐;cas需手动循环实现条件递增;load/store须配对保障内存可见性;结构体需转unsafe.pointer操作。

atomic.AddInt64 是计数器唯一安全的自增方式
直接对 int 或 int32 变量做 ++ 或 +=,在并发下必然触发 data race——Go 的 go run -race 会立刻报出 Data race on variable。根本原因:读、加、写三步不原子,中间可能被其他 goroutine 插入并覆盖。
必须用 atomic.AddInt64,且目标变量类型必须是 int64(不能是平台相关的 int):
-
int64在所有主流平台(amd64/arm64)上天然 8 字节对齐,CPU 能用单条指令完成原子操作 -
int32虽也支持,但在 64 位系统上若未对齐(如嵌在结构体非首字段),可能 panic 或行为未定义 - 局部变量取地址传给
atomic函数有逃逸风险,建议声明为包级变量或确保其生命周期稳定
CompareAndSwapInt64 不是“条件自增”,而是“乐观重试基础”
atomic.CompareAndSwapInt64 本身不提供加法能力,它只做一件事:当当前值等于预期旧值时,才原子地换成新值,并返回 true。它常被用于实现无锁初始化、状态跃迁或 CAS loop,但不是开箱即用的“if x == 5 then x += 1”。
想实现带条件的递增,得手动写循环:
func tryIncrementIfLessThan(max int64) bool {
for {
old := atomic.LoadInt64(&counter)
if old >= max {
return false
}
if atomic.CompareAndSwapInt64(&counter, old, old+1) {
return true
}
// 失败:别人抢先改了,重新读再试
}
}
- CAS 循环里必须每次重新
Load,否则会基于过期值判断 - 没有 ABA 保护,高并发下极端情况可能误判(如值从 A→B→A),真实系统需结合版本号或
atomic.Value缓存 - 热路径中频繁失败会吃满 CPU,应设最大重试次数,超限后退化为
sync.Mutex
Load/Store 必须配对使用,否则内存可见性不保
原子操作不只是“防止撕裂读写”,更关键的是建立 happens-before 关系。比如用 atomic.StoreInt64(&flag, 1) 写状态,后续 goroutine 必须用 atomic.LoadInt64(&flag) 读,才能保证看到写入的值和它之前的全部内存写入(如数据初始化)。
常见错误:
- 写用
atomic.StoreInt64,读却用普通flag == 1—— 编译器或 CPU 可能重排、缓存旧值,导致永远读不到更新 - 多个相关变量(如
data和ready)没统一用原子操作串联,ready看到了,data却还是零值 - 误以为
atomic.AddInt64自带读屏障,其实它只保证自身加法原子,不担保之前写的其他变量可见
指针和结构体不能直接原子操作,得靠 unsafe.Pointer 拆解
sync/atomic 不支持对结构体或任意对象做原子操作。想“原子替换整个配置”,只能把结构体指针转成 unsafe.Pointer,再用 atomic.StorePointer 和 atomic.LoadPointer。
示例:
type Config struct {
Timeout int
Retries int
}
var configPtr unsafe.Pointer = unsafe.Pointer(&defaultConfig)
func UpdateConfig(newCfg *Config) {
atomic.StorePointer(&configPtr, unsafe.Pointer(newCfg))
}
func GetCurrentConfig() *Config {
return (*Config)(atomic.LoadPointer(&configPtr))
}
- 必须确保
*Config生命周期长于任何正在读它的 goroutine,否则会悬垂指针 - 不能对结构体内部字段单独原子读写;如果要部分更新,得用
atomic.Value封装,或换用sync.RWMutex -
unsafe.Pointer操作绕过 Go 类型系统,编译器无法检查,出错时 panic 位置往往远离问题源头
atomic,而在只加了一半。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











