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

在 Go Memory Model 文档http://golang.org/ref/mem 中,它给出了以下示例:


var a string

var done bool


func 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。那正确吗?


谢谢你。


蝴蝶刀刀
浏览 196回答 2
2回答

慕勒3428872

有很多事情可能会出错。它可以:在第一个 goroutine 完成后安排 setup goroutine。对本地寄存器而不是全局寄存器进行更改。(增加整数会快得多)部分更新(不太可能使用 bool,但字符串可能有问题)完全放弃更改在当前的实现中,发生了非常接近问题 1 的事情。假设 GOMAXPROCS=1,for !done { }永远不会屈服于调度程序。这意味着安装程序永远不会运行。goroutine 在内存分配、通道通信、系统调用和函数调用上随机产生。这是一个非详尽的清单。但是它不会在什么都不做的 for 循环中产生。您需要某种形式的同步来确保 goroutine 最终产生。我想指出的是,当前的实现中是否存在问题并不重要。关键是他们已经声明这不是保证,并且当他们实现优化时,他们将假定 main 观察到 done 的代码和未观察到的代码相同。

眼眸繁星

Go 编程语言规范Go 语句“go”语句在同一地址空间内作为独立的并发控制线程或 goroutine 开始执行函数调用。函数值和参数在调用 goroutine 中照常评估,但与常规调用不同,程序执行不会等待调用的函数完成。相反,该函数开始在新的 goroutine 中独立执行。当函数终止时,它的 goroutine 也会终止。如果函数有任何返回值,它们会在函数完成时被丢弃。该setup()够程可能无法运行:“不像正常通话,程序执行不等待调用的函数来完成。”
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go