The code in sync/atomic.once.go is :
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 { //A
//if o.done == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
f()
atomic.CompareAndSwapUint32(&o.done, 0, 1) //B
//o.done = 1
}
}
I don't think the two 'atomic-style' code A,B above is necessary or useful. I think the lock is enough, and it could be ok if A,B are not atomic style. I must miss something, please be kind to tell me the purpose of the code A,B. Thank you.
The original is correct. The reason is that the Go Memory Model says, that without synchronization (if o.done == 1) the changes to o.done might not be observed at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With