# 数据结构
type Once struct { | |
done atomic.Uint32 // 0 = unused, 1 = used,用于标志操作是否操作 | |
m Mutex // 锁,用来第一操作时候,加锁处理 | |
} |
# 源码
func (o *Once) Do(f func()) { | |
// 快路径:无锁判断 | |
// 若已为 1,直接返回,避免加锁开销 | |
if o.done.Load() == 0 { | |
o.doSlow(f) | |
} | |
} | |
func (o *Once) doSlow(f func()) { | |
// 慢路径:有人看到 done ==0, 需要串行化进入临界区 | |
o.m.Lock() | |
defer o.m.Unlock() | |
// 双重检查:可能在当前 goroutine 申请到锁之前,别的 goroutine 已经把 f 执行过了 | |
if o.done.Load() == 0 { | |
// 将 o.donw 值设置为 1,用来标记操作完成 | |
defer o.done.Store(1) | |
// 真正执行业务函数 | |
f() | |
} | |
} |