您好,登錄后才能下訂單哦!
這篇文章主要介紹“GoLang中的sync包Once如何使用”,在日常操作中,相信很多人在GoLang中的sync包Once如何使用問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”GoLang中的sync包Once如何使用”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
Once 包主要用于在并發(fā)執(zhí)行代碼的時(shí)候,某部分代碼只會(huì)被執(zhí)行 一次。
Once 的使用也非常簡(jiǎn)單,Once 只有一個(gè) Do 方法,接收一個(gè)無(wú)參數(shù)無(wú)返回值的函數(shù)類(lèi)型的參數(shù) f,不管調(diào)用多少次 Do 方法,參數(shù) f 只在第一次調(diào)用 Do 方法時(shí)執(zhí)行。
我們有一個(gè)Msg 參數(shù),多個(gè)協(xié)程都會(huì)用到他,但是這個(gè)參數(shù)只用初始化一次就可以。
package main import ( "fmt" "sync" "time" ) var msg string func main() { var one sync.Once for i := 0; i < 5; i++ { go func(i int) { one.Do(func() { fmt.Printf("%d 執(zhí)行初始化!\n", i) msg = "Your Need Data" }) fmt.Println(msg) }(i) } time.Sleep(3* time.Second) }
執(zhí)行結(jié)果如下:
可以看到初始化的代碼只被4號(hào)線程執(zhí)行了一次, 其他協(xié)程都是直接讀的初始化的數(shù)據(jù),并沒(méi)有執(zhí)行初始化的函數(shù)。
不要在 Do()
方法的參數(shù)方法中再次調(diào)用Do()
方法,因?yàn)閳?zhí)行這個(gè)Do()
方法的參數(shù)方法的時(shí)候,One 會(huì)持有一個(gè)鎖,如果再參數(shù)方法中再次調(diào)用Do()
方法,就會(huì)等待這個(gè)鎖釋放, 導(dǎo)致參數(shù)方法無(wú)法執(zhí)行完畢,然后外層的Do 方法就一直無(wú)法釋放鎖,最后就成了死鎖。
錯(cuò)誤示例:
package main import ( "fmt" "sync" ) var msg string var one sync.Once func main() { one.Do(fun1) } func fun1(){ fmt.Println("我是 fun1") one.Do(fun2) } func fun2(){ fmt.Println("我是 fun2") }
執(zhí)行結(jié)果:
可以知道再 fun1()
中使用 Do()
方法調(diào)用 fun2
的時(shí)候形成了死鎖, 因?yàn)樵?fun1()
執(zhí)行過(guò)程中已將持有了該鎖,需要 fun1()
執(zhí)行完畢才會(huì)釋放,然后因?yàn)槭褂?Do()
方法執(zhí)行 fun2()
也會(huì)請(qǐng)求這個(gè)鎖, 會(huì)一直等待,導(dǎo)致 fun1()
不可能執(zhí)行完, 也不可能釋放鎖。成了死鎖。
查看源碼
func (o *Once) Do(f func()) { if atomic.LoadUint32(&o.done) == 0 { // Outlined slow-path to allow inlining of the fast-path. 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() } }
使用一個(gè)原子類(lèi)作為標(biāo)識(shí),加鎖校驗(yàn)和操作原子類(lèi),保證只會(huì)被一個(gè)協(xié)程執(zhí)行。
Do
調(diào)用了 doSlow
, 在 doSlow
中有defer
關(guān)鍵字,表示執(zhí)行函數(shù)和釋放鎖是倒序執(zhí)行,必須先執(zhí)行完畢 if
判斷和里面的 f()
才能釋放鎖。
到此,關(guān)于“GoLang中的sync包Once如何使用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。