Go同步原语与数据竞争:原子操作(atomic)

在Go并发编程中,当多个 goroutine 同时读写共享变量时,如果没有妥善同步,就会出现数据竞争(Data Race) 。Go 提供了 sync/atomic 包,用于实现轻量级的原子操作,避免使用锁所带来的性能开销。


一、什么是原子操作?

原子操作指的是在执行过程中不会被任何其他操作中断的操作。在多线程环境中,原子操作确保某个变量的读、写、加减等操作具有一致性和安全性。


二、常用原子操作函数

Go 的 sync/atomic 包支持以下常用操作,主要用于 int32int64uint32uint64unsafe.Pointer 等类型:

函数 说明
atomic.LoadInt32(&val) 原子读取值
atomic.StoreInt32(&val, new) 原子写入值
atomic.AddInt32(&val, delta) 原子加法(并返回新值)
atomic.CompareAndSwapInt32(&val, old, new) 原子比较并交换
同理还有 Int64Uint32Uint64Pointer 版本

三、使用示例

示例:并发计数器

go 复制代码
package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    var counter int32 = 0
    var wg sync.WaitGroup

    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            atomic.AddInt32(&counter, 1)
        }()
    }

    wg.Wait()
    fmt.Println("Final Counter:", counter) // 输出应该为 1000
}

这个例子中我们使用 atomic.AddInt32 来确保并发写入是安全的,避免了 race condition


四、CompareAndSwap:原子级条件更新

CompareAndSwap 是一个非常强大的函数,可用于实现无锁状态切换。

go 复制代码
var status int32 = 0

// 尝试将状态从 0 改为 1
if atomic.CompareAndSwapInt32(&status, 0, 1) {
    fmt.Println("切换状态成功")
} else {
    fmt.Println("状态已被修改")
}

如果当前值等于期望值,就会被新值替换;否则不做任何操作,适用于状态机、CAS 重试等场景。


五、原子 vs 锁

方面 原子操作(atomic) 锁(Mutex/RWMutex)
性能 极高(CPU级指令) 较低(涉及调度、抢占)
适用场景 简单计数、状态标记 复杂结构同步
编程复杂度 较高,易出错 较低,语义清晰
死锁风险 存在风险

六、使用注意事项

  • • 原子操作仅适用于简单变量的并发读写,如计数器、标志位。
  • • 不能对结构体、map、slice 等复杂类型直接使用。
  • • 原子操作不能和普通操作混用,否则仍可能产生竞态条件。
  • • 如需读写多个变量或复合结构,推荐使用 sync.Mutex

七、小结

  • sync/atomic 提供了高性能的原子操作,是无锁并发的核心工具。
  • • 适合用于计数器、自旋锁、状态标识等场景。
  • • 不适合管理复杂共享数据,不能代替所有同步手段。

相关推荐
晴殇i15 小时前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
掘金者阿豪15 小时前
🚀 CentOS Stream 9服务器Docker部署KWDB:从零到跨模查询实战全记录
后端
yang_xin_yu15 小时前
一文带你精通泛型PECS原则与四大核心函数式接口
后端
孟陬15 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
树獭叔叔15 小时前
13-KV Cache与位置编码表:大模型推理加速的核心技术
后端·aigc·openai
想用offer打牌15 小时前
一站式了解四种限流算法
java·后端·go
嘻哈baby15 小时前
用 C++ 写线程池是怎样一种体验?
后端
嘻哈baby15 小时前
SQL Server 和 Oracle 以及 MySQL 有哪些区别?
后端
绝无仅有15 小时前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
武子康15 小时前
大数据-237 离线数仓 - Hive 广告业务实战:ODS→DWD 事件解析、广告明细与转化分析落地
大数据·后端·apache hive