Go語言并發(fā)編程 sync.Once
sync.Once
用于保證某個動作只被執(zhí)行一次,可用于單例模式中,比如初始化配置。我們知道init()函數(shù)也只會執(zhí)行一次,不過它是在main()
函數(shù)之前執(zhí)行,如果想要在代碼執(zhí)行過程中只運行某個動作一次,可以使用sync.Once
,下面來介紹一下它的使用方法。
先來看下面的代碼:
package main import ( "fmt" "sync" ) func main() { var num = 6 var once sync.Once add_one := func() { num = num + 1 } minus_one := func() { num = num - 1 } once.Do(add_one) fmt.Printf("The num: %d\n", num) once.Do(minus_one) fmt.Printf("The num: %d\n", num) }
執(zhí)行結(jié)果:
The num: 7
The num: 7
sync.Once
類型提供了一個Do
方法,Do方法只接受一個參數(shù),且參數(shù)類型必須是func()
,也就是沒有參數(shù)聲明和結(jié)果聲明的函數(shù)。
Do
方法只會執(zhí)行首次被調(diào)用時傳入的那個函數(shù),只執(zhí)行一次,也不會執(zhí)行其它函數(shù)。上面的例子中,即使傳入的函數(shù)不同,也只會執(zhí)行第一次傳入的那個函數(shù)。如果有多個只執(zhí)行一次的函數(shù),需要為每一個函數(shù)分配一個sync.Once
類型的值:
func main() { var num = 6 var once1 sync.Once var once2 sync.Once add_one := func() { num = num + 1 } minus_one := func() { num = num - 1 } once1.Do(add_one) fmt.Printf("The num: %d\n", num) once2.Do(minus_one) fmt.Printf("The num: %d\n", num) }
sync.Once
類型是一個結(jié)構(gòu)體類型,一個是名為done
的uint32
類型字段,還有一個互斥鎖m
。
type Once struct { done uint32 m Mutex }
done
字段的值只可能是0或者1,Do
方法首次調(diào)用完成后,done
的值就變?yōu)榱?。done的值使用四個字節(jié)的uint32
類型的原因是為了保證對它的操作是“原子操作”,通過調(diào)用atomic.LoadUint32
函數(shù)獲取它的值,如果為1,直接返回,不會執(zhí)行函數(shù)。
如果為0,Do方法會立即鎖定字段m,如果這里不加鎖,多個goroutine
同時執(zhí)行到Do方法時判斷都為0,則都會執(zhí)行函數(shù),所以Once
是并發(fā)安全的。
加鎖之后,會再次檢查done
字段的值,如果滿足條件,執(zhí)行傳入的函數(shù),并用原子操作函數(shù)atomic.StoreUint32
將done
的值設(shè)置為1。
下面是Once的源碼:
func (o *Once) Do(f func()) { if atomic.LoadUint32(&o.done) == 0 { o.doSlow(f) } } func (o *Once) doSlow(f func()) { o.m.Lock() defer o.m.Unlock() if o.done == 0 { defer atomic.StoreUint32(&o.done, 1) f() } }
源碼非常簡潔,和GoF 設(shè)計模式中的單例模式非常相似。
到此這篇關(guān)于Go語言并發(fā)編程 sync.Once的文章就介紹到這了,更多相關(guān)Go語言 sync.Once內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入了解Go的interface{}底層原理實現(xiàn)
本文主要介紹了Go的interface{}底層原理實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Go使用協(xié)程批量獲取數(shù)據(jù)加快接口返回速度
這篇文章主要介紹了Go使用協(xié)程批量獲取數(shù)據(jù)加快接口返回速度,使用Go語言后,可以并發(fā)獲取,極大提升效率,需要的朋友可以參考下2023-02-02