Go 并发编程实战课
晁岳攀(鸟窝)
前微博技术专家,知名微服务框架 rpcx 作者
25635 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 22 讲
Go 并发编程实战课
15
15
1.0x
00:00/00:00
登录|注册

12 | atomic:要保证原子操作,一定要使用这几种方法

atomic.Value的扩展
内存屏障的作用
赋值操作的原子性
使用atomic实现Lock-Free queue
扩展atomic的API
Value类型
Store
Load
Swap
CAS (CompareAndSwap)
Add
实现lock-free数据结构
实现自定义的基本并发原语
使用场景举例
应用于底层优化
多处理器多核系统中的原子操作实现
CPU提供的基础原子操作
原子操作的定义
提供了一些实现原子操作的方法
实现同步算法底层的原子的内存操作原语
总结
第三方库的扩展
atomic提供的方法
atomic原子操作的应用场景
原子操作的基础知识
atomic包
atomic原子操作

该思维导图由 AI 生成,仅供参考

你好,我是鸟窝。
前面我们在学习 Mutex、RWMutex 等并发原语的实现时,你可以看到,最底层是通过 atomic 包中的一些原子操作来实现的。当时,为了让你的注意力集中在这些原语的功能实现上,我并没有展开介绍这些原子操作是干什么用的。
你可能会说,这些并发原语已经可以应对大多数的并发场景了,为啥还要学习原子操作呢?其实,这是因为,在很多场景中,使用并发原语实现起来比较复杂,而原子操作可以帮助我们更轻松地实现底层的优化。
所以,现在,我会专门用一节课,带你仔细地了解一下什么是原子操作,atomic 包都提供了哪些实现原子操作的方法。另外,我还会带你实现一个基于原子操作的数据结构。好了,接下来我们先来学习下什么是原子操作。

原子操作的基础知识

Package sync/atomic 实现了同步算法底层的原子的内存操作原语,我们把它叫做原子操作原语,它提供了一些实现原子操作的方法。
之所以叫原子操作,是因为一个原子在执行的时候,其它线程不会看到执行一半的操作结果。在其它线程看来,原子操作要么执行完了,要么还没有执行,就像一个最小的粒子 - 原子一样,不可分割。
CPU 提供了基础的原子操作,不过,不同架构的系统的原子操作是不一样的。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

原子操作在并发编程中扮演着重要角色,它通过sync/atomic包提供的方法来确保操作的原子性,类似于一个不可分割的最小粒子。不同系统架构的原子操作实现方式不同,但Go语言提供了通用的原子操作API,封装了不同架构下的实现。使用atomic可以实现底层优化,简化并发原语的复杂逻辑,提高性能,并作为实现lock-free数据结构的基石。sync/atomic包提供了Add、CompareAndSwap、Swap、Load、Store等方法,用于不同类型的原子操作。此外,文章还介绍了第三方库对atomic的扩展,以及使用atomic实现Lock-Free queue的示例。这些内容全面展示了原子操作的重要性和应用场景,对于并发编程有着重要的指导意义。文章还讨论了对一个地址的赋值是否是原子操作,以及现代多核系统中对原子操作的追求,引入了内存屏障的概念。最后,提出了思考题,鼓励读者尝试为Value类型增加Swap和CompareAndSwap方法,以及分享今天的内容给朋友或同事。整体而言,本文深入浅出地介绍了原子操作的基本概念、应用方法和相关技术挑战,对读者快速了解并发编程中的原子操作具有重要的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 并发编程实战课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(20)

  • 最新
  • 精选
  • myrfy
    恰好老婆大人是做芯片MMU相关工作的,咨询了一下她,她告诉我现代的CPU基本上都在硬件层面保证了多核之间数据视图的一致性,也就是说普通的LOAD/STORE命令在硬件层面处理器就可以保证cache的一致性。如果是这样的话,那是不是可以理解为atomic包对指针的作用,主要是防止编译器做指令重排呢?因为编译器在这些现代架构上没必要使用特殊的指令了。 如果不止这样,麻烦老师指正,晚上回去和老婆大人再深入交流交流……

    作者回复: atomic主要是对这几种cpu架构的封装。你老婆是对的,你可以好好请教一下你老婆

    2020-11-06
    10
    38
  • 端贺
    晁老师的内功真是深厚,整个系列读下来还是有点吃力的,尤其是文中推荐的外链,需要多花点时间好好消化,感谢晁老师。

    作者回复: 加油!!!赞你认真的态度

    2020-11-14
    2
    5
  • 末班车
    老师您好,之前在用atomic的时候,疑惑为啥没有提供it int16的相关方法,这是不是也跟内存对齐有关系啊?

    作者回复: Go官方运行时只支持32bit/64bit系统,最小支持单位就是32bit

    2020-11-06
    3
  • Geek_921929
    晁老师,go包 cas针对ABA问题有啥封装吗,度学堂看到你的直播了哈哈,然后后来回放找不到了

    作者回复: 没有。aba问题是应用层自己解决的,比如用version

    2021-09-21
    2
  • 赵敷
    晁老师你好,我有几个问题想向你请求一下。第一点,go的原子操作,是否有禁止指令重排的作用。即有一个func代码如下: var s1 int32 var s2 int32 var s3 int var s4 int func f() { 1: atomic.StoreInt32(&s1,1) 2: s3=1 3: atomic.StoreInt32(&s2,1) 4: s4 = 1 } 我想问一下1指令一定在3指令之前执行吗,另外2指令一定在s4指令之前执行吗。另外在内存模型上,我知道原子操作底层会遵循MESI模型来保证数据在多核缓存的一致性,我想知道多线程访问上面f函数,当我们在一个协程里观测到3指令已经执行,是否可以认为2也已经执行(如果3不是原子操作,我知道这一点肯定无法保证),2对内存的访问结果,对观测线程是否可见。也就是说添加原子指令的位置,会添加内存屏障,但是对于写内存屏障,是该屏障之前所有写操作都会刷新到内存,还是只是针对那个store的原子变量会刷新到内存,其他普通写操作还是继续写到cache中,逐级淘汰到内存中

    作者回复: 我的理解只会对那个store的变量刷新。

    2022-12-05归属地:北京
  • 强庚
    atomic.Load系列的原子操作具体作用是什么呢?比如if atomic.LoadInt32(&a) == 1 如果直接写成if a== 1这样有什么问题吗

    作者回复: 保证别的地方的对a写你能感知到

    2022-10-13归属地:北京
  • 小袁
    atomic.Value是怎样实现的呢?这里为啥可以支持任意的数据?用Pointer类型不香么?

    作者回复: 这不就是为了便利性嘛

    2021-04-23
    2
  • Fan
    老师,执行这条命令,报错是什么意思,怎样解决? $ GOARCH=amd64 go tool objdump -gnu main.o flag provided but not defined: -gnu usage: go tool objdump [-S] [-s symregexp] binary [start end] -S print go code alongside assembly -s string only dump symbols matching this regexp

    作者回复: 升级go版本

    2020-12-24
  • SuperDai
    老师,无锁队列对消费者数量和生产者数量是不是有要求?是不是要求消费者数量为1还是生产者数量为1?

    作者回复: 没有要求,但我个人觉得数量不易过大

    2020-11-12
    2
  • SuperDai
    老师,无锁队列对消费者数量和生产者数量是不是有要求?是不是要求消费者数量为1还是生产者数量为1?

    作者回复: 没有要求

    2020-11-12
收起评论
显示
设置
留言
20
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部