在 Go Memory Model 文档http://golang.org/ref/mem 中,它给出了以下示例:var a stringvar done boolfunc setup() { a = "hello, world" done = true}func main() { go setup() for !done { } print(a)}然后它说明了这个例子的以下内容。“无法保证 main 会观察到对 done 的写入,因为两个线程之间没有同步事件。main 中的循环不能保证完成。”因此,如果main可能没有观察到对done变量的写入,这似乎表明setup()函数永远不会运行。那是对的吗?如果是这样,是不是因为程序被重新排序以在for !done {}循环之后移动go setup()?或者会不会有其他原因?我假设如果go setup()语句实际上能够执行,那么将保证调用setup()函数并设置done。那正确吗?谢谢你。
2 回答
慕勒3428872
TA贡献1848条经验 获得超6个赞
有很多事情可能会出错。它可以:
在第一个 goroutine 完成后安排 setup goroutine。
对本地寄存器而不是全局寄存器进行更改。(增加整数会快得多)
部分更新(不太可能使用 bool,但字符串可能有问题)
完全放弃更改
在当前的实现中,发生了非常接近问题 1 的事情。假设 GOMAXPROCS=1,for !done { }
永远不会屈服于调度程序。这意味着安装程序永远不会运行。
goroutine 在内存分配、通道通信、系统调用和函数调用上随机产生。这是一个非详尽的清单。但是它不会在什么都不做的 for 循环中产生。您需要某种形式的同步来确保 goroutine 最终产生。
我想指出的是,当前的实现中是否存在问题并不重要。关键是他们已经声明这不是保证,并且当他们实现优化时,他们将假定 main 观察到 done 的代码和未观察到的代码相同。
- 2 回答
- 0 关注
- 194 浏览
添加回答
举报
0/150
提交
取消