Concurrency Go Memory Model文档中给出的本例中的故障原因是什么?
在Go Memory模型文档中,它给出了以下示例:Concurrency Go Memory Model文档中给出的本例中的故障原因是什么?,concurrency,go,Concurrency,Go,在Go Memory模型文档中,它给出了以下示例: var a string var done bool func setup() { a = "hello, world" done = true } func main() { go setup() for !done { } print(a) } 然后,它说了下面这个例子 由于两个线程之间没有同步事件,因此无法保证main会观察到要完成的写操作。main中的循环不保证完成 因此,如果mai
var a string
var done bool
func setup() {
a = "hello, world"
done = true
}
func main() {
go setup()
for !done {
}
print(a)
}
然后,它说了下面这个例子
由于两个线程之间没有同步事件,因此无法保证main会观察到要完成的写操作。main中的循环不保证完成
因此,如果main可能没有观察到对done变量的写入,这似乎表明setup()函数从未运行。对吗?如果是这样的话,是不是因为程序被重新排序,将go setup()移动到之后!完成{}循环?还是会有其他原因
我假设如果实际能够执行go setup()语句,那么setup()函数将保证被调用并设置done。是这样吗
多谢各位
“go”语句将函数调用的执行作为
控件内的独立并发控制线程或goroutine
相同的地址空间
对函数值和参数进行了评估
在呼叫goroutine中与往常一样,但与常规呼叫不同,
程序执行不会等待调用的函数完成。
相反,函数开始以新的方式独立执行
戈鲁廷。当函数终止时,其goroutine也
终止。如果函数有任何返回值,它们将被丢弃
当函数完成时
setup()
goroutine可能不会运行:“与常规调用不同,程序执行不会等待调用的函数完成。”可能会出现很多问题。它可以:
for!完成{}
将永远不会向调度程序屈服。这意味着安装程序永远不会运行
一个goroutine在内存分配、通道通信、系统调用和随机函数调用方面都有收益。这是一份非详尽的清单。但它不会在一个什么都不做的for循环上让步。您需要某种形式的同步,以确保goroutine最终生成
我想指出,当前的实现中是否存在问题并不重要。关键是他们已经声明这是不保证的,当他们实现优化时,他们将假定main观察到的代码是完成的,而没有观察到的代码是相同的。很抱歉,但我不理解该段的哪一部分暗示setup()可能无法运行。我看到这种情况的唯一方法是对“go setup()”语句和“for!done{}”语句进行代码重新排序。是这样吗?如果没有,循环似乎会阻止执行,直到设置“完成”。@sixfingeredman:没有代码重新排序,只有并发:“一个'go'语句在同一地址空间内作为独立的并发控制线程或goroutine启动函数调用的执行。”但如果没有代码重新排序,然后goroutine将启动并执行“setup()”函数,主线程将继续运行,并运行到“for!done{}”循环中,不是吗?@sixfingeredman:One处理器和
main
永远不会放弃控制或GOMAXPROCS=1
。啊,因此问题将特定于单个操作系统线程的情况,因此,“for”循环实际上会阻止“setup()”函数,即使它是一个单独的goroutine。是吗?我想我明白你的意思了,但是你能澄清一下“第一次跑步后”是什么意思吗?我不完全明白你在说什么。谢谢你的澄清。这更有道理。是的,我知道重点是不要像给定的示例那样编写代码。我只是想确保我理解这些问题,所以我一定会以不同的形式发现相同的问题。:-)