­

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、完成。

Tags: