Reputation: 2500
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.
Upvotes: 0
Views: 63
Reputation: 53458
There are many things that can go wrong. It could:
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.
Upvotes: 1
Reputation: 166714
The Go Programming Language Specification
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."
Upvotes: 1