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

相关推荐
Piper蛋窝6 小时前
深入 Go 语言垃圾回收:从原理到内建类型 Slice、Map 的陷阱以及为何需要 strings.Builder
后端·go
六毛的毛8 小时前
Springboot开发常见注解一览
java·spring boot·后端
AntBlack8 小时前
拖了五个月 ,不当韭菜体验版算是正式发布了
前端·后端·python
31535669138 小时前
一个简单的脚本,让pdf开启夜间模式
前端·后端
uzong9 小时前
curl案例讲解
后端
一只叫煤球的猫9 小时前
真实事故复盘:Redis分布式锁居然失效了?公司十年老程序员踩的坑
java·redis·后端
yanlele10 小时前
前端面试第 75 期 - 2025.07.06 更新前端面试问题总结(12道题)
前端·javascript·面试
大鸡腿同学10 小时前
身弱武修法:玄之又玄,奇妙之门
后端
DemonAvenger10 小时前
高性能 TCP 服务器的 Go 语言实现技巧:从原理到实践
网络协议·架构·go
Code季风11 小时前
深入理解微服务中的服务注册与发现(Consul)
java·运维·微服务·zookeeper·架构·go·consul