Reputation: 444
I am reading the official document, there is a code that I can't understand.
var a string
var done bool
func setup() {
a = "hello, world"
done = true
}
func doprint() {
if !done {
once.Do(setup)
}
print(a)
}
func twoprint() {
go doprint()
go doprint()
}
This version can (incorrectly) print an empty string instead of "hello, world".
Why this code may produce wrong results.
Upvotes: 0
Views: 555
Reputation: 23
Just to further explain the accepted answer, in Go, compilers and processors may reorder reads/writes. In a single go routine, such reordering is guaranteed to not affect the behavior.
However, in your example, there are multiple go routines without synchronization and reordering DOES have an impact. Imagine the first go routine executes done=true
then a=xxxx
, if the second go routine executes after first done=true
and before a=xxxx
, it will produce an empty string.
Upvotes: 0
Reputation: 418555
Because in doprint()
the done
variable is is accessed (read) without synchronization.
Imagine the first goroutine running doprint()
completes before the second is scheduled to run. The first writes done
(in setup()
), and the 2nd goroutine tries to read done
: should that read produce the result written by the first goroutine? There is no synchronization: undefined behavior. It may be that done
will be observed as true
, and thus setup()
will not be called, and it may be the write to a
will not be observed and thus the initial zero value (empty string) is printed.
Reads of variables always observe previous writes (previous in time) in a single goroutine. Writes made by a goroutine are not guaranteed to be observed in another goroutine unless there is synchronization between them.
Upvotes: 3