go 初学者,在看《 GO 高级编程》,对于下面这句话不是很理解,
https://chai2010.gitbooks.io/advanced-go-programming-book/content/ch1-basic/ch1-05-mem.html
“更糟糕的是,因为两个线程之间没有同步事件,setup 线程对 done 的写入操作甚至无法被 main 线程看到,main 函数有可能陷入死循环中。”
var a string
var done bool
func setup() {
a = "hello, world"
done = true
}
func main() {
go setup()
for !done {}
print(a)
}
在 main 的 for 循环里检查 done 的值,即使某一次检查恰好与 setup 设置 done 相冲突,在下次 for 的检查应该也能发现 done 被设为 true 了啊,为什么会说“ setup 线程对 done 的写入操作甚至无法被 main 线程看到”呢?
1
mind3x 2018-08-14 15:34:51 +08:00 via Android
请搜索“内存模型”
简单的说,现代 CPU 的乱序执行特性使得有可能 done=true 发生在 a 赋值以前。 |
2
flyingpine OP @mind3x 多谢回复,是的,这个可以解释前一句话:“但是 Go 语言并不保证在 main 函数中观测到的对 done 的写入操作发生在对字符串 a 的写入的操作之后,因此程序很可能打印一个空字符串。” 对于我的问题,刚才又读了很多文档,一个可能的解释是 main thread 的空循环会导致 CPU 不能被调度到 setup,所以 setup 一直得不到执行。
|
3
gamexg 2018-08-14 18:12:35 +08:00
是的,除了你说的还有另外一个可能:
我对汇编忘的差不多了, 编译器可能会优化成这样:main 将 done 的值读到了寄存器,之后循环全部是从寄存器读取的,并未去读取内存,所以可能永远不知道 setup 的变更。 |