我正在阅读官方文档,有一个我不懂的代码。
var a string
var done bool
func setup() {
a = "hello, world"
done = true
}
func doprint() {
if !done {
once.Do(setup)
}
print(a)
}
func twoprint() {
go doprint()
go doprint()
}
This version can (incorrectly) print an empty string instead of "hello, world".
为什么此代码可能会产生错误的结果。
最佳答案
因为在doprint()
中,无需同步即可访问(读取)done
变量。
想象一下,第一个goroutine运行doprint()
在第二个goroutine计划运行之前完成了。第一个写入done
(在setup()
中),第二个goroutine尝试读取done
:读取的结果应该产生第一个goroutine写入的结果吗?没有同步:未定义的行为。可能是done
将被观察为true
,因此将不会调用setup()
,并且可能会是未观察到对a
的写入,因此将打印初始零值(空字符串)。
变量的读取始终遵循单个goroutine中的先前写入(时间先前)。 goroutine所做的写入不能保证在另一个goroutine中得到观察,除非它们之间存在同步。
关于go - 关于golang并发的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60540573/