惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
月光博客
月光博客
T
Tailwind CSS Blog
阮一峰的网络日志
阮一峰的网络日志
小众软件
小众软件
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
罗磊的独立博客
Jina AI
Jina AI
酷 壳 – CoolShell
酷 壳 – CoolShell
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
量子位
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
美团技术团队
博客园 - 聂微东
V
V2EX

郑文峰的博客

使用dify对接飞书多维表格 使用n8n对接飞书多维表格 服务启动时出现 OOM 一次服务升级时pg表DDL执行超时失败 Go语言高效IO缓冲技术详解 Go语言延迟初始化(Lazy Initialization)最佳实践 Go语言字符串拼接性能对比与优化指南 Go语言结构体内存对齐完全指南 Go语言空结构体:零内存消耗的高效编程 Go语言堆栈分配与逃逸分析深度解析 Go语言内存预分配完全指南 Go语言不可变数据共享:无锁并发编程实践 Go语言零拷贝技术完全指南 Go语言遍历性能深度解析:从原理到优化实践 Go语言Interface Boxing原理与性能优化指南 Go协程池深度解析:原理、实现与最佳实践 使用etcd分布式锁导致的协程泄露与死锁问题 基于pre-commit的Python代码规范落地实践 初识 MCP Server pulsar阻塞导致logstash无法接入日志 django-prometheus使用及源码分析 kube-proxy源码分析 kubernetes service如何通过iptables转发 tcp缓存引起的日志丢失 django-apschedule定时任务异常停止 理解calico容器网络通信方案原理 理解flannel的三种容器网络方案原理 理解Linux IPIP隧道 理解VXLAN网络 理解Linux TunTap设备
Go语言原子操作完全指南
zhengwenfeng · 2025-06-14 · via 郑文峰的博客

# 前言

原子操作是指不可中断的一个或一系列操作,这些操作要么全部执行成功,要么全部不执行。在Go语言中,通过sync/atomic包提供原子操作支持。允许在不适用互斥锁的情况下安全地并发访问共享数据,加锁会引入协调开销,性能可能会下降,而原子操作使用 CPU 指令直接在硬件层面进行操作,从而有更高的性能。

# 原子操作 vs 互斥锁

特性 原子操作 互斥锁
性能 更高(CPU指令级支持) 较低(需要系统调用)
使用场景 简单内存操作 复杂代码块保护
可操作性 有限(仅支持基本类型) 灵活(可保护任意代码)

# 原子操作使用场景

# 1. 计数器实现

var requestCount atomic.Int64 // Go 1.19+新版API

// 处理请求时安全递增计数器
func HandleRequest() {
    requestCount.Add(1) // 原子递增
}

// 获取当前请求数
func GetRequestCount() int64 {
    return requestCount.Load()
}

1
2
3
4
5
6
7
8
9
10
11

# 2. 状态标志控制

var shutdown atomic.Int32

func mainLoop() {
    for {
        if shutdown.Load() == 1 {
            break
        }
        // do work
    }
}

func stop() {
    shutdown.Store(1)
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3. 单次初始化(替代sync.Once)

var initialized atomic.Int32

func maybeInit() {
    if initialized.CompareAndSwap(0, 1) {
        // 只有第一个调用者会执行这里
    }

    // 其他调用者直接返回
}

1
2
3
4
5
6
7
8
9

# 4. 无锁栈数据结构实现

type node struct {
    next *node
    val  any
}

var head atomic.Pointer[node]

func push(n *node) {
    for {
        old := head.Load()
        n.next = old
        if head.CompareAndSwap(old, n) {
            return
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 性能对比测试

针对使用互斥锁和原子操作的 Benchmark

func BenchmarkAtomicIncrement(b *testing.B) {
	var counter atomic.Int64
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			counter.Add(1)
		}
	})
}

func BenchmarkMutexIncrement(b *testing.B) {
	var (
		counter int64
		mu      sync.Mutex
	)
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			mu.Lock()
			counter++
			mu.Unlock()
		}
	})
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

运行结果如下,原子操作要比加互斥锁快上约 40%。

$ go test  -bench=. -benchmem .
goos: darwin
goarch: arm64
pkg: main/demo
cpu: Apple M4 Pro
BenchmarkAtomicIncrement-12     22237474                55.00 ns/op            0 B/op          0 allocs/op
BenchmarkMutexIncrement-12      13650686                84.53 ns/op            0 B/op          0 allocs/op
PASS
ok      main/demo       2.841s

1
2
3
4
5
6
7
8
9

# 总结

  • 优先使用原子操作的场景:

    • 计数器、状态标志等简单共享变量
    • 性能敏感的并发控制
    • 无锁数据结构实现
  • 需要使用互斥锁的场景:

    • 保护复杂逻辑代码块
    • 需要保护多个变量的不变
    • 执行IO操作等耗时任务时