I am trying to understand the example with incorrect sync code from The Go Memory Model.
Double-checked locking is an attempt to avoid the overhead of synchronization. For example, the twoprint program might be incorrectly written as:
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()
}
but there is no guarantee that, in
doprint
, observing the write to done implies observing the write toa
. This version can (incorrectly) print an empty string instead of"hello, world"
.
What are the detailed reasons for an empty string printed in place of "hello world"? I ran this code about five times, and every time, it printed "hello world".
Would the compiler swap a line a = "hello, world"
and done = true
for optimization? Only in this case, I can understand why an empty string would be printed.
Thanks a lot! At the bottom, I've attached the changed code for the test.
package main
import(
"fmt"
"sync"
)
var a string
var done bool
var on sync.Once
func setup() {
a = "hello, world"
done = true
}
func doprint() {
if !done {
on.Do(setup)
}
fmt.Println(a)
}
func main() {
go doprint()
go doprint()
select{}
}