为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go Memory Model 文档中给出的这个例子中失败的原因是什么?

在 Go Memory Model 文档中给出的这个例子中失败的原因是什么?

Go
蝴蝶刀刀 2021-08-30 15:18:50
在 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个赞

有很多事情可能会出错。它可以:

  1. 在第一个 goroutine 完成后安排 setup goroutine。

  2. 对本地寄存器而不是全局寄存器进行更改。(增加整数会快得多)

  3. 部分更新(不太可能使用 bool,但字符串可能有问题)

  4. 完全放弃更改

在当前的实现中,发生了非常接近问题 1 的事情。假设 GOMAXPROCS=1,for !done { }永远不会屈服于调度程序。这意味着安装程序永远不会运行。

goroutine 在内存分配、通道通信、系统调用和函数调用上随机产生。这是一个非详尽的清单。但是它不会在什么都不做的 for 循环中产生。您需要某种形式的同步来确保 goroutine 最终产生。


我想指出的是,当前的实现中是否存在问题并不重要。关键是他们已经声明这不是保证,并且当他们实现优化时,他们将假定 main 观察到 done 的代码和未观察到的代码相同。


查看完整回答
反对 回复 2021-08-30
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

Go 编程语言规范

Go 语句

“go”语句在同一地址空间内作为独立的并发控制线程或 goroutine 开始执行函数调用。

函数值和参数在调用 goroutine 中照常评估,但与常规调用不同,程序执行不会等待调用的函数完成。相反,该函数开始在新的 goroutine 中独立执行。当函数终止时,它的 goroutine 也会终止。如果函数有任何返回值,它们会在函数完成时被丢弃。

setup()够程可能无法运行:“不像正常通话,程序执行不等待调用的函数来完成。”


查看完整回答
反对 回复 2021-08-30
  • 2 回答
  • 0 关注
  • 194 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信