答案: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. 实际使用示例
下面是一个并发安全的计数器示例:
Shakker
多功能AI图像生成和编辑平台
103 查看详情
package mainimport ( "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 int32var config map[string]stringfunc 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导致逻辑复杂。
以上就是Golang如何使用sync/atomic实现原子操作的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1135474.html
微信扫一扫
支付宝扫一扫