Go中实现并发安全计数器应优先用sync/atomic进行原子操作(如atomic.AddInt64),适用于简单整型;复杂逻辑或非原子类型则用sync.Mutex保护,封装为结构体并确保临界区无阻塞;务必用go run -race检测数据竞争。
在 Go 中实现并发安全计数器,核心是避免多个 goroutine 同时读写同一变量导致的数据竞争。最直接可靠的方式是使用 sync/atomic 包进行原子操作,或用 sync.Mutex 加锁保护。两者适用场景不同:原子操作轻量高效,适合简单整型计数;互斥锁更通用,支持复杂逻辑和多种数据类型。
sync/atomic 提供无锁、底层硬件支持的原子增减操作,适用于 int32、int64、uint32、uint64 和指针等类型。它比加锁更快,且不会发生死锁。
int64),不能用 int(其大小依赖平台)atomic.AddInt64(&counter, 1) 增加,atomic.LoadInt64(&counter) 读取,atomic.SwapInt64 或 atomic.CompareAndSwapInt64 实现条件更新
复合逻辑(如“仅当小于100才加1”),应优先考虑 CompareAndSwap 或退回到 mutex当计数逻辑涉及判断、多字段联动(如带最大值限制、重置时间戳)、或非原子类型(如 map 计数、浮点数、结构体)时,sync.Mutex 是更稳妥的选择。
sync.Mutex 作为结构体字段(推荐嵌入 sync.RWMutex 若读远多于写)mu.Lock() / mu.RLock(),结束后用 defer mu.Unlock() 确保释放Go 自带竞态检测器(race detector)是发现数据竞争的最有效手段。它不能替代正确设计,但能帮你暴露潜在问题。
go run -race main.go 或 go test -race
很多初学者尝试用 channel 或全局变量模拟计数器,结果引入复杂性或性能瓶颈。
map[int]int 等非线程安全容器直接并发读写,即使 key 不同也不安全(map 内部有共享哈希表状态)github.com/cespare/xxhash + sync.Pool 优化分配