Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24054 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

30 | 原子操作(下)

郝林 2018-10-19
你好,我是郝林,今天我们继续分享原子操作的内容。
我们接着上一篇文章的内容继续聊,上一篇我们提到了,sync/atomic包中的函数可以做的原子操作有:加法(add)、比较并交换(compare and swap,简称 CAS)、加载(load)、存储(store)和交换(swap)。并且以此衍生出了两个问题。
今天我们继续来看第三个衍生问题: 比较并交换操作与交换操作相比有什么不同?优势在哪里?
回答是:比较并交换操作即 CAS 操作,是有条件的交换操作,只有在条件满足的情况下才会进行值的交换。
所谓的交换指的是,把新值赋给变量,并返回变量的旧值。
在进行 CAS 操作的时候,函数会先判断被操作变量的当前值,是否与我们预期的旧值相等。如果相等,它就把新值赋给该变量,并返回true以表明交换操作已进行;否则就忽略交换操作,并返回false
可以看到,CAS 操作并不是单一的操作,而是一种操作组合。这与其他的原子操作都不同。正因为如此,它的用途要更广泛一些。例如,我们将它与for语句联用就可以实现一种简易的自旋锁(spinlock)。
for {
if atomic.CompareAndSwapInt32(&num2, 10, 0) {
fmt.Println("The second number has gone to zero.")
break
}
time.Sleep(time.Millisecond * 500)
}
for语句中的 CAS 操作可以不停地检查某个需要满足的条件,一旦条件满足就退出for循环。这就相当于,只要条件未被满足,当前的流程就会被一直“阻塞”在这里。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(10)

  • heha37
    回答问题:
    1. 是否一定要操作引用类型的值;
    2. 是否一定要操作nil;
    3. 是否需要处理一个接口的不同类型。
    2018-11-12
    8
  • rename
    我认为最重要的三点是 要操作的变量类型,操作频率和整体操作耗时。请郝大指教~

    作者回复: 其实主要还是变量类型,原子操作在这块是严格的。能用原子就用原子。锁这个原语还是相对较重。

    2018-10-27
    2
  • Askerlve
    老师,git代码没更新哦~😯
    2018-10-19
    2
  • 翅膀
    请教下关于读写的原子操作底层的问题,对于一个32位的整数,什么情况下会读写一半。假如这个值定义时做了字节对齐(存储地址是4的整数倍),还会有这种情况吗?如果再加限制,仅仅针对intel的现代cpu,比如i7,情况又是怎样的?
    2018-11-15
    1
  • sky
    郝大 关于这两节的原子操作提供的一些方法能具体列下相应常用的业务场景就更好了 这样才能更好的学以致用啊
    2018-10-25
    1
  • Askerlve
    思考题:1.使用原子类型有ABA问题,若业务对ABA敏感,使用锁。
    只想到了一点,求老师补充~😀
    2018-10-19
    1
    1
  • Da Vinci
    在首次真正使用后,原子值就不应该再被复制了,这句话不是特别理解,想请老师再解释一下

    作者回复: Value 类型的值里面一旦存了值就不应该再拷贝了,因为这很可能会让基于内存地址的互斥机制失效,并产生混乱。这也是 Value 的文档里特别说明的。

    2019-11-11
  • 全时N多只
    有个疑问:语言层可以保证原子操作自身读、写时的正确性,但如何保证读出后用于业务判断的正确性呢?我理解业务判断已经在atomic方法之外了,还是无法保证数据使用的一致性

    作者回复: 数据一致性是一个比较大的话题了。没有上下文的话几乎是无从谈起的。

    2019-05-08
  • 顾骨
    int32这种类型是4个字节的,64位操作系统下,a=b这种赋值操作不是原子的吗?为什么还要LoadInt32这个原子操作?
    2018-12-12
  • 冰激凌的眼泪
    value的封装使用,可以参照后面的并发map
    2018-11-01
收起评论
10
返回
顶部