go中sync.Once源碼解讀
sync.Once
前言
本次的代碼是基於go version go1.13.15 darwin/amd64
sync.Once的作用
根據名字就大致能猜到這個函數的作用,就是使用sync.once
的對象只能執行一次。
我們在errgroup
就能看到它的身影
type Group struct {
cancel func()
wg sync.WaitGroup
errOnce sync.Once
err error
}
他保證了,只會記錄第一個出錯的goroutine
的錯誤信息
實現原理
// Once is an object that will perform exactly one action.
type Once struct {
// 0未執行,1執行了
done uint32
// 互斥鎖
m Mutex
}
裏面就一個對外的函數
func (o *Once) Do(f func()) {
// 原子的讀取done的值,如果為0代表onec第一次的執行還沒有出發
if atomic.LoadUint32(&o.done) == 0 {
// 執行
o.doSlow(f)
}
}
func (o *Once) doSlow(f func()) {
// 加鎖
o.m.Lock()
defer o.m.Unlock()
// 判斷done變量為0表示還沒執行第一次
if o.done == 0 {
// 計數器原子的加一
defer atomic.StoreUint32(&o.done, 1)
// 執行傳入的函數
f()
}
}
總結
1、總體上也是很簡單一個計數器,一把互斥鎖,通過atomic.LoadUint32
的原子讀取技術器中的值;
2、如果計數器中的值為0表示還沒有執行;
3、加鎖,執行傳入的函數,然後通過atomic.StoreUint32
原子的對計數器的值進行加一操作;
4、完成。