答案:Go语言中sync/atomic包提供int32、int64等基础类型的原子操作,如Add、Load、Store、Swap和CompareAndSwap,适用于计数器、状态标志等简单共享变量场景,相比互斥锁更轻量高效;通过atomic.AddInt64实现并发安全计数器,用CompareAndSwap实现CAS逻辑可构建无锁算法,如一次性初始化,但复杂类型需间接处理,且不宜滥用CAS导致逻辑混乱。

在Go语言中,sync/atomic 包提供了对基本数据类型的原子操作支持,能够避免多个goroutine同时访问共享变量时出现竞态条件。相比互斥锁(mutex),原子操作更轻量,适用于简单的共享变量读写场景,比如计数器、状态标志等。
1. 原子操作支持的数据类型
注意: atomic包只支持以下几种基础类型:
- int32、int64
- uint32、uint64
- uintptr
- unsafe.Pointer
对于结构体或复杂类型,不能直接使用原子操作,需通过指针或其他方式间接处理。
2. 常见原子操作函数
以 int64 为例,atomic 提供了几个核心函数:
立即学习“go语言免费学习笔记(深入)”;
- atomic.AddInt64(&value, delta):原子地增加值
- atomic.LoadInt64(&value):原子地读取值
- atomic.StoreInt64(&value, newValue):原子地写入值
- atomic.SwapInt64(&value, newValue):原子地交换值
- atomic.CompareAndSwapInt64(&value, old, new):如果当前值等于old,则设为new
3. 实际使用示例
下面是一个并发安全的计数器示例:
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var counter int64
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 1000; j++ {
atomic.AddInt64(&counter, 1)
}
}()
}
wg.Wait()
fmt.Println("最终计数:", atomic.LoadInt64(&counter))
}
在这个例子中,多个goroutine同时对 counter 进行递增,使用 atomic.AddInt64 和 atomic.LoadInt64 确保操作的原子性,避免了使用 mutex 的开销。
4. 使用CAS实现自定义同步逻辑
Compare-And-Swap(CAS)是实现无锁算法的核心。例如,可以用它来实现一个只执行一次的操作(类似 sync.Once):
var initialized int32
var config map[string]string
func setup() {
if atomic.LoadInt32(&initialized) == 0 {
atomic.CompareAndSwapInt32(&initialized, 0, 1)
config = make(map[string]string)
config["mode"] = "prod"
}
}
这里先判断是否初始化,再通过 CAS 设置状态,确保只初始化一次。虽然 sync.Once 更推荐用于此场景,但 CAS 提供了更大的灵活性。
基本上就这些。只要涉及共享变量的简单读写,优先考虑 atomic,性能更高,代码也更清晰。关键是记住:不要对非原子类型做原子操作,也不要滥用CAS导致逻辑复杂。










