首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在使用atomics时需要加载

为什么在使用atomics时需要加载
EN

Stack Overflow用户
提问于 2021-07-08 23:14:12
回答 1查看 114关注 0票数 2

在Go (和其他语言如c++)中使用atomics时,建议使用原子加载操作来读取并发写入的值。

如果原子写入(无论是存储还是整数增量)的定义(据我理解)是,没有线程可以查看部分写入,那么为什么需要原子加载?

如果仅在内存地址上使用原子存储,内存地址的普通负载是否总是安全的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-09 00:23:49

这个答案主要针对C和C++,因为我并不直接熟悉其他许多语言中的atomics,但我怀疑它们是相似的。

在某些情况下,许多实际机器确实是这样工作的。例如,在x86-64上,普通加载指令对于普通存储区是原子的,或者是锁定的读-修改-写入指令。因此,对于可以加载单个指令的类型,原则上可以使用普通赋值,避免撕裂。

但在某些情况下,这是行不通的。例如:

  • 不是无锁的类型(例如,多于一对单词的结构)。在这种情况下,加载或存储需要几个指令,因此必须在它们周围安装锁,否则完全有可能撕裂。atomic加载函数知道要使用锁,普通的赋值是不会的。
  • 类型可以是无锁定,但需要特殊处理。例如,x86-32上的64位long long int。一个普通的加载将执行两个32位整数加载指令(这些指令分别是原子的),所以即使存储是原子的,它也可能发生在两者之间。但是atomic加载函数可以发出64位浮点或SIMD负载,虽然效率较低,但可以在一个原子指令中完成。关于哥德螺栓的实例

因此,当存储和加载都使用所提供的atomic函数时,该语言只承诺原子性。-C或C++的“定义”不准确。通过要求程序员始终使用atomic负载,该语言提供了一个“钩子”,实现可以在需要时采取适当的操作。在普通负载已经足够的情况下,实现可以相应地进行优化,而不会丢失任何东西。

另一点是,atomic加载提供了一个位置,以便在需要的时候设置一个内存屏障(除relaxed之外的任何排序)。一些体系结构包括带有内置屏障的加载指令(例如a 64的ldar),并且在语言级别将屏障作为负载的一部分,使编译器更容易利用这一点。如果您必须执行常规的赋值,然后调用屏障函数,那么编译器就很难知道它可以将它们优化到ldar中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68309532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档