哪些数据类型本质上是原子的

时间:2014-11-15 20:00:04

标签: go atomicity

我想知道Go中的哪些数据类型本质上是线程安全的(如果有的话)。

我的假设是int,floats和bools是安全的,而复合类型则不是。

  • 我的假设是否正确?
  • 对于改变复合类型与替换它有不同的考虑因素吗?
  • 频道怎么样?

谢谢。

2 个答案:

答案 0 :(得分:5)

我不相信他们中的任何一个都是保证是原子的,但有些可能是在实践中(当然,通过原子,我们的意思是分配到它们同时来自两个线程将产生一个或另一个值,而不是一些第三个值(例如每个值的位组合) - 我们并不意味着你可以原子地比较商店或类似的东西)。最好的办法是查看Go Memory Model

答案 1 :(得分:2)

  

请注意:

如果在编译它的同一平台上运行代码,则对单个字值进行变换通常应该是原子的。但是还有更多的东西使得必须使用原子指令(如果你不打算使用更强的保证)。

原因是除了编译器级别的内存重新排序之外,您可能在CPU级别进行了重新排序以进行优化。 (写入不会立即传播到主存储器,CPU有存储缓冲区等)。

因此,在多线程环境中,您需要明确地对所有内核显示更改,否则您将损坏内存。

就改变复合类型而言,是的,你需要(非常)小心。最简单的方法是锁定整个对象(嵌入互斥锁是一种很好的方法,它更加缓存友好)。

否则,如果您想以原子方式执行此操作,则可以采用读取 - 复制 - 更新方法(查找RCU或写入时复制),但请注意!除非你真的知道自己在做什么,否则你很容易陷入困境。如果将可变对象嵌套到其他可变对象中(查找有关嵌套无锁数据结构的可线性化的问题),那么很难做到这一点。这真的很棘手,我劝阻它。即使您要添加额外的间接级别以使您的数据结构看起来不可变,解决并发原子读取,更新和删除的问题也是博士级别的东西。如果你很好奇,请查找Aleksandar Prokopec的论文和论文:http://axel22.github.io/home/professional/

这就是渠道和互斥体为您服务的原因。而且我希望通道在已经很好的性能上有所提升。现在通道对于一些人来说很容易,但是我花了几天时间才能真正地绕过它们。但是一旦完成,使用起来非常简单。