【发布时间】:2017-05-15 08:39:23
【问题描述】:
假设我有这个:
go func() {
for range time.Tick(1 * time.Millisecond) {
a, b = b, a
}
}()
还有其他地方:
i := a // <-- Is this safe?
对于这个问题,i 相对于原始a 或b 的值是什么并不重要。唯一的问题是阅读a 是否安全。也就是说,a 是否有可能是 nil、部分分配、无效、未定义、...不是有效值?
I've tried to make it fail 但到目前为止它总是成功(在我的 Mac 上)。
我无法在The Go Memory Model 文档中找到除此引用之外的任何具体内容:
读取和写入大于单个机器字的值的行为类似于 以未指定的顺序进行多个机器字大小的操作。
这是否暗示单个机器字写入实际上是原子的?如果是这样,Go 中的函数指针写入是否是单个机器字操作?
【问题讨论】:
-
我想是的。看看这个:(play.golang.org/p/b-fyvCiR7b) 指针的大小总是4字节。在 32 位处理器中,字长为 32 位(4 字节)。显然,在 64 位处理器中,您有 8 个字节的字。因此,基于此以及您从文档中发布的 sn-p,我会说它是安全的。
-
@AmirKeibi 需要注意的重要一点是,文档中的 保证 不说的是单机字操作 是原子的。它只是说大于单个机器字的操作是无序的。实际上,无论读写是否是单个机器字操作,仍然无法保证(Go 也无法保证)该操作是原子的。它依赖于硬件,从 Go 的角度来看是未定义的,因此需要同步。
-
我认为问题标题有点误导。并发读取是安全的,但是当涉及到至少一个写入操作时,一切都会崩溃。
标签: go concurrency goroutine