Go Memory Model文档中给出的此示例中的失败原因是什么?

问题描述:

In the Go Memory Model document http://golang.org/ref/mem it gives the following example:

var a string
var done bool

func setup() {
    a = "hello, world"
    done = true
}

func main() {
    go setup()
    for !done {
    }
    print(a)
}

It then says the following of this example.

"there is no guarantee that the write to done will ever be observed by main, since there are no synchronization events between the two threads. The loop in main is not guaranteed to finish."

So if the write to the done variable may not be observed by main, that would seem to suggest that the setup() function never runs. Is that correct? If so, would it be because the program was reordered to move the go setup() after the for !done {} loop? Or would there be some other reason?

I assume that if the go setup() statement is actually able to be executed, then the setup() function would be guaranteed to be called and done would be set. Is that right?

Thank you.

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

  var字符串
var done bool 
 \  nfunc setup(){
a =“ hello,world” 
 done = true 
} 
 
func main(){
 go setup()
 for!done {
} 
 print(a)  
} 
  code>  pre> 
 
 

然后显示此示例的以下内容。 p>

” 因为两个线程之间没有同步事件,所以main永远不会观察到完成写入。main中的循环不能保证完成。“ p> blockquote>

因此,如果 main strong>可能未观察到对 done strong>变量的写入,则似乎表明 setup() strong>函数从不运行 。 那是对的吗? 如果是这样,是否是因为对循环之后,该程序已重新排序以移动 go setup() strong>? 还是会有其他原因? p>

我认为,如果实际上能够执行 go setup() strong>语句,则 setup( ) strong>功能将被确保被调用,并且完成 strong>将会被设置。 是吗? p>

谢谢。 p> div>

There are many things that can go wrong. It could:

  1. schedule the setup goroutine for after the first goroutine completes.
  2. make the change to a local register instead of the global. (incrementing integers would be much faster)
  3. partially update (unlikely with a bool, but a string could be problematic)
  4. drop the change entirely

In the current implementation, something very close to problem 1 occurs. Assuming GOMAXPROCS=1, for !done { } will never yield to the scheduler. This means setup would never run.

A goroutine yields on memory allocation, channel communication, syscalls, and randomly on function calls. That is a non-exhaustive list. But it will not yield on a for loop that does nothing. You need some form of synchronization to ensure the goroutine eventually yields.


I would like to point out that it doesn't matter whether there is a problem or not in the current implementation. The point is they have declared it is not guaranteed and when they implement optimizations, they will assume code where done is observed by main and code where it is not observed as the same.

The Go Programming Language Specification

Go statements

A "go" statement starts the execution of a function call as an independent concurrent thread of control, or goroutine, within the same address space.

The function value and parameters are evaluated as usual in the calling goroutine, but unlike with a regular call, program execution does not wait for the invoked function to complete. Instead, the function begins executing independently in a new goroutine. When the function terminates, its goroutine also terminates. If the function has any return values, they are discarded when the function completes.

The setup() goroutine may not run: "unlike with a regular call, program execution does not wait for the invoked function to complete."