变量赋值在go中是原子的吗?

utugiqy6  于 2022-12-16  发布在  Go
关注(0)|答案(2)|浏览(233)

如果我有两个线程同时修改一个结构体上的字符串字段,我是否总是看到一个或另一个字符串被赋给该字段,而没有其他内容?

ukxgm1gy

ukxgm1gy1#

不需要。如果需要原子操作,可以使用sync/atomic
Go Memory Model将包含所有相关详细信息。从内存模型文档的顶部:
修改同时被多个goroutine访问的数据的程序必须串行化这种访问。
要序列化访问,请使用通道操作或其他同步原语(如syncsync/atomic包中的原语)保护数据。

os8fio9y

os8fio9y2#

截至今天,2022年6月6日的Go memory model版本保证不大于机器字的内存访问是原子的。
否则,不大于机器字的存储器位置x的读取r必须观察到某个写入w,使得r不在w之前发生,并且没有写入w“,使得w在w”之前发生,并且w“在r之前发生。即,每个读取必须观察到由先前或并发写入所写入的值。
然而,字符串肯定比机器字大,所以你的访问不能保证是原子的,在这种情况下,结果是不确定的,但它很可能是来自不同写入的不同部分的交错。
鼓励但不要求大于单个机器字的存储器位置的读取满足与字大小的存储器位置相同的语义,观察单个允许的写入w。出于性能原因,实施方案可改为将较大操作视为一组以未指定次序的个别机器字大小的操作。这意味着多字数据结构上的争用可能导致不对应于单个写入的不一致值。(指针,长度)或(指针,类型)对,就像大多数Go语言实现中的接口值、Map、切片和字符串一样,这样的竞争反过来会导致任意的内存破坏。
注意,sync/atomic不仅提供原子性,而且提供顺序一致性,因此,对于不大于机器字的访问,sync/atomic仅提供额外的顺序一致性。
sync/atomic包中的API统称为“原子操作”,可以用来同步不同goroutine的执行,如果原子操作A的效果被原子操作B观察到,那么A就在B之前被同步。程序中执行的所有原子操作就好像是按照某种连续一致的顺序执行的。
前面的定义与C++的顺序一致原子和Java的volatile变量具有相同的语义。

相关问题