30 | 原子操作(下)
30 | 原子操作(下)
讲述:黄洲君
时长09:46大小8.94M
知识扩展
总结
思考题
赞 18
提建议
精选留言(18)
- heha372018-11-12回答问题: 1. 是否一定要操作引用类型的值; 2. 是否一定要操作nil; 3. 是否需要处理一个接口的不同类型。36
- Geek_f1933b2020-01-18郝老师,什么时候使用atomic.value呢,有没有具体的应用中的简单例子呢
作者回复: 其实需要保护非引用类型的值的时候都挺适用的。如果是引用类型的值的话,可能会起不到保护作用。因为我们修改的往往是这个值引用的那个底层值,而 atomic.Value 只会保护这个值本身。 例子的话...比如保护全局配置、同时保护一坨全局计数、保护 bit array,等等。
14 - rename2018-10-27我认为最重要的三点是 要操作的变量类型,操作频率和整体操作耗时。请郝大指教~
作者回复: 其实主要还是变量类型,原子操作在这块是严格的。能用原子就用原子。锁这个原语还是相对较重。
11 - 蜉蝣2020-11-06老师好,衍生问题 4 的回答不能明白。既然原子操作是不会被中断的,那么为什么还会出现 “如果写操作还没有进行完,读操作就来读了,那么就只能读到仅修改了一部分的值。” 这种写操作还没完进行完就有其他操作进来? 如果是因为多核多 CPU 的话,那是不是说,读的原子操作与写的原子操作是互斥?
作者回复: 原文中的“如果写操作还没有进行完,读操作就来读了,那么就只能读到仅修改了一部分的值。”这句话是对读写锁来说的。如果只锁写操作、不锁读操作就会发生这样的问题。 这种原子操作一般都是通过原生的CPU指令实现的,所以从底层保障了并发操作的安全性。即使CPU是多核的,甚至有多个CPU,只要主板等硬件方面没有问题,都是可以保障的。 最后,原子操作和互斥锁不是一个东西。原子操作用防中断的方式来保并发,而互斥锁用串行化多个操作的方式来保并发(它不防中断)。 你如果说的只是“互斥”这个词,那你也可以理解为针对同一个变量的原子操作是“互斥”的(但它是通过“防中断”来达到“互斥”的目的)。
共 2 条评论6 - sky2018-10-25郝大 关于这两节的原子操作提供的一些方法能具体列下相应常用的业务场景就更好了 这样才能更好的学以致用啊5
- 翅膀2018-11-15请教下关于读写的原子操作底层的问题,对于一个32位的整数,什么情况下会读写一半。假如这个值定义时做了字节对齐(存储地址是4的整数倍),还会有这种情况吗?如果再加限制,仅仅针对intel的现代cpu,比如i7,情况又是怎样的?3
- Askerlve2018-10-19老师,git代码没更新哦~😯3
- 冰激凌的眼泪2018-11-01value的封装使用,可以参照后面的并发map2
- Askerlve2018-10-19思考题:1.使用原子类型有ABA问题,若业务对ABA敏感,使用锁。 只想到了一点,求老师补充~😀共 2 条评论2
- mkii2021-02-25一旦atomic.Value类型的值(以下简称原子值)被真正使用,它就不应该再被复制了。 老师,如果Value存储的是引用类型,被复制有可能绕过原子值进行非并发操作这个我可以理解。但如果Value存储的是值类型,如果复制了再对这个副本操作应该不会对原值有影响。这里是怕别人误操作产生歧义吗?(即,我明明通过copyValue.store改了值,但为什么没生效?)
作者回复: Value里面存储的是被操作值的指针啊,所以一样的。
共 3 条评论1 - poettian2021-01-10看到衍生问题4我也有个疑惑,那如果不用原子操作,是不是说假如在写的同时有读的操作,我们读取变量实际读到的是个不完整的值?
作者回复: 是有这个可能的。
1 - noisyes2022-06-23通过一个或多个公开的函数,让外界间接地使用到它。这种情况下不要把原子值传递到外界,不论是传递原子值本身还是它的指针值。 但是即使编写了一个函数,但是不传递原子值的话,怎么才可以让外界使用它呢。
作者回复: 靠复制啊,如果是值类型的值的话,从函数返回时就自动复制了,如果是引用类型的值的话,比如切片或字典,就需要手动复制。使用atomic.Value的时候一定要注意这类问题。
- 六维2022-06-18老师,关于热更有什么方案呢? 是否有使用过,并在实际的项目中运用过? 有没有相应的事例?
作者回复: 热更新的话,现在肯定是首选 context 啊,因为标准库中的其他包已经与 context 融合得非常好了。虽然现在市面上还有一些相关的第三方库,但是如果没有特殊需求的话,还还是推荐 context。
共 3 条评论 - jxs12112021-10-24go的内置函数的源码是在哪里可以找到,比如说append()使用时,都做了什么
作者回复: 要看切片相关的话,先在源码 src 目录里找runtime/slice.go 。这个文件里有个 growslice 函数,append 会调用它。后边你就顺藤摸瓜吧。
- lesserror2021-08-17郝林老师,demo64 中的 示例3 的第二条 打印: fmt.Printf("Store %d to box2.\n", v3) 是不是 应该 改为: fmt.Printf("Store %d to box3.\n", v3)展开
作者回复: 好像应该是 box3 ,回头我改一下吧,谢谢
- Da Vinci2019-11-11在首次真正使用后,原子值就不应该再被复制了,这句话不是特别理解,想请老师再解释一下
作者回复: Value 类型的值里面一旦存了值就不应该再拷贝了,因为这很可能会让基于内存地址的互斥机制失效,并产生混乱。这也是 Value 的文档里特别说明的。
- 一颗大白菜2019-05-08有个疑问:语言层可以保证原子操作自身读、写时的正确性,但如何保证读出后用于业务判断的正确性呢?我理解业务判断已经在atomic方法之外了,还是无法保证数据使用的一致性
作者回复: 数据一致性是一个比较大的话题了。没有上下文的话几乎是无从谈起的。
- 顾骨2018-12-12int32这种类型是4个字节的,64位操作系统下,a=b这种赋值操作不是原子的吗?为什么还要LoadInt32这个原子操作?