hardPass
hardPass

Reputation: 20851

Is the two atomic style code in sync/atomic.once.go necessary?

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.

Upvotes: 3

Views: 300

Answers (1)

zzzz
zzzz

Reputation: 91321

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.

Upvotes: 4

Related Questions