Concurrency Go Memory Model文档中给出的本例中的故障原因是什么?

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

在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中的循环不保证完成

因此,如果main可能没有观察到对done变量的写入,这似乎表明setup()函数从未运行。对吗?如果是这样的话,是不是因为程序被重新排序,将go setup()移动到之后!完成{}循环?还是会有其他原因

我假设如果实际能够执行go setup()语句,那么setup()函数将保证被调用并设置done。是这样吗

多谢各位

“go”语句将函数调用的执行作为 控件内的独立并发控制线程或goroutine 相同的地址空间

对函数值和参数进行了评估 在呼叫goroutine中与往常一样,但与常规呼叫不同, 程序执行不会等待调用的函数完成。 相反,函数开始以新的方式独立执行 戈鲁廷。当函数终止时,其goroutine也 终止。如果函数有任何返回值,它们将被丢弃 当函数完成时


setup()
goroutine可能不会运行:“与常规调用不同,程序执行不会等待调用的函数完成。”

可能会出现很多问题。它可以:

  • 计划在第一个goroutine完成后的安装goroutine
  • 对本地寄存器而不是全局寄存器进行更改。(增加整数会快得多)
  • 部分更新(bool不太可能,但字符串可能有问题)
  • 完全放弃改变
  • 在当前的实现中,出现了非常接近问题1的情况。假设GOMAXPROCS=1,
    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。是吗?我想我明白你的意思了,但是你能澄清一下“第一次跑步后”是什么意思吗?我不完全明白你在说什么。谢谢你的澄清。这更有道理。是的,我知道重点是不要像给定的示例那样编写代码。我只是想确保我理解这些问题,所以我一定会以不同的形式发现相同的问题。:-)