Once 保证操作只执行一次
- 适用于一些单例、配置的加载等
内部数据结构
go
type Once struct {
done atomic.Uint32
m Mutex
}
done用于标识操作是否已经完成只有0或1m互斥锁
核心方法
-
Doscssfunc (o *Once) Do(f func()) { if o.done.Load() == 0 { o.doSlow(f) } } func (o *Once) doSlow(f func()) { o.m.Lock() defer o.m.Unlock() if o.done.Load() == 0 { defer o.done.Store(1) f() } } -
原子加载
done值是否为0 -
如果等于
0说明f func()并没有被初始化 -
进入
doSlow方法 -
加锁,然后再次原子加载
done值是否为0。这里进行可一个double check,确保当前done的值没有被修改 -
执行
f func(),然后将done标记为1
once这个并发原底层代码非常简洁,也很好理解。