six fingered man
six fingered man

Reputation: 2500

What is the cause of failure in this example given in the Go Memory Model document?

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

Answers (2)

Stephen Weinberg
Stephen Weinberg

Reputation: 53458

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.

Upvotes: 1

peterSO
peterSO

Reputation: 166714

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."

Upvotes: 1

Related Questions