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 的变更。 |