2. sync.Once原理
sync.Once 是 Go 语言提供的内置并发安全的单次执行的对象,开箱即用。sync.Once 的原理非常简单,只有一个 Do 方法,其原型如下:
func (o *Once) Do(f func()) {}
Do 方法接收一个函数作为参数,当第一次调用 Do 方法时,会执行传入的函数 f,并且会将 done 置为 true,当第二次调用 Do 方法时,会直接返回,不会再次执行函数 f。
sync.Once 的内部结构如下:
type Once struct {
m Mutex
done uint32
}
sync.Once 内部有一个互斥锁 m,同时有一个 done 标识,用于标识函数是否已经执行。
sync.Once 的 Do 方法的实现如下:
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()
}
}
sync.Once 的 Do 方法的实现非常简单,只有两个步骤:
- 判断 done 是否为 1,如果为 1,则直接返回
- 如果 done 不为 1,则加锁,然后再次判断 done 是否为 1,如果为 1,则直接返回,如果不为 1,则执行函数 f,并将 done 置为 1
3. sync.Once的使用
sync.Once 的使用非常简单,直接声明变量即可,不需要初始化。sync.Once 的声明如下:
var once = sync.Once{}
sync.Once 的操作如下:
once.Do(func() {
// 需要执行的函数
})
4. sync.Once的注意事项
- sync.Once 不能在创建后再进行复制操作。
- sync.Once 与其他结构不同,它不是一个结构体,因此我们在声明的时候只需要声明变量即可,不需要初始化。