郑文峰的博客 郑文峰的博客
首页
  • Go语言高性能编程
分类
标签
归档
关于
  • 导航 (opens new window)
  • 代码片段 (opens new window)
  • 收藏
  • 友链
  • 外部页面

    • 开往 (opens new window)
GitHub (opens new window)

zhengwenfeng

穷则变,变则通,通则久
首页
  • Go语言高性能编程
分类
标签
归档
关于
  • 导航 (opens new window)
  • 代码片段 (opens new window)
  • 收藏
  • 友链
  • 外部页面

    • 开往 (opens new window)
GitHub (opens new window)
  • python

  • go语言

    • go简单使用grpc
    • gin中validator模块的源码分析
    • 优化gin表单的错误提示信息
    • go中如何处理error
    • tcp缓存引起的日志丢失
    • 使用etcd分布式锁导致的协程泄露与死锁问题
    • go语言高性能编程

      • Go协程池深度解析:原理、实现与最佳实践
      • Go语言Interface Boxing原理与性能优化指南
      • Go语言遍历性能深度解析:从原理到优化实践
      • Go语言零拷贝技术完全指南
      • Go语言不可变数据共享:无锁并发编程实践
      • Go语言内存预分配完全指南
      • Go语言原子操作完全指南
        • 前言
        • 原子操作 vs 互斥锁
        • 原子操作使用场景
          • 1. 计数器实现
          • 2. 状态标志控制
          • 3. 单次初始化(替代sync.Once)
          • 4. 无锁栈数据结构实现
        • 性能对比测试
        • 总结
      • Go语言堆栈分配与逃逸分析深度解析
      • Go语言空结构体:零内存消耗的高效编程
      • Go语言结构体内存对齐完全指南
      • Go语言字符串拼接性能对比与优化指南
      • Go语言延迟初始化(Lazy Initialization)最佳实践
      • Go语言高效IO缓冲技术详解
  • linux

  • 其他

  • 编程
  • go语言
  • go语言高性能编程
zhengwenfeng
2025-06-14
目录

Go语言原子操作完全指南

# 前言

原子操作是指不可中断的一个或一系列操作,这些操作要么全部执行成功,要么全部不执行。在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操作等耗时任务时
#go语言#go语言高性能编程
上次更新: 2025/06/14, 16:16:07
Go语言内存预分配完全指南
Go语言堆栈分配与逃逸分析深度解析

← Go语言内存预分配完全指南 Go语言堆栈分配与逃逸分析深度解析→

最近更新
01
Go语言高效IO缓冲技术详解
06-14
02
Go语言延迟初始化(Lazy Initialization)最佳实践
06-14
03
Go语言字符串拼接性能对比与优化指南
06-14
更多文章>
Theme by Vdoing | Copyright © 2022-2025 zhengwenfeng | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式