once结构是这样的
type Once struct {
m Mutex
done uint32
}
其中只有这么一个方法
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
作用是保证多个协程只执行某个函数一次
为什么不能使用CAS原子操作来替代锁呢?
if atomic.CompareAndSwapUint32(&o.done, 0, 1){
f()
}
在多线程调用如下代码的情况下
once.DO(a)
b()
若用原子操作,多线程情况下,执行b的时候,a并不一定成功执行(可能第一次调用Do的线程正在执行中,别的线程再调用会直接返回,造成并未成功执行a的情况下执行b)