最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

GoLang中的sync包Once使用執(zhí)行示例

 更新時(shí)間:2023年03月06日 10:43:57   作者:水淹萌龍  
這篇文章主要介紹了GoLang中的sync包Once使用執(zhí)行示例,沒有學(xué)習(xí)Once前,大家可能想到 聲明一個(gè)標(biāo)識(shí),表示是否初始化過,然后初始化這個(gè)標(biāo)識(shí)加鎖,更新這個(gè)標(biāo)識(shí),Once包主要用于在并發(fā)執(zhí)行代碼的時(shí)候,某部分代碼只會(huì)被執(zhí)行一次

背景

在系統(tǒng)初始化的時(shí)候,某些代碼只想被執(zhí)行一次,這時(shí)應(yīng)該怎么做呢,沒有學(xué)習(xí) Once 前,大家可能想到 聲明一個(gè)標(biāo)識(shí),表示是否初始化過,然后初始化這個(gè)標(biāo)識(shí)加鎖,更新這個(gè)標(biāo)識(shí)。

但是學(xué)會(huì)了 One 的使用可以更加簡(jiǎn)單的解決這個(gè)問題

One簡(jiǎn)介

Once 包主要用于在并發(fā)執(zhí)行代碼的時(shí)候,某部分代碼只會(huì)被執(zhí)行 一次。

Once 的使用也非常簡(jiǎn)單,Once 只有一個(gè) Do 方法,接收一個(gè)無參數(shù)無返回值的函數(shù)類型的參數(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ù),并沒有執(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ù)方法無法執(zhí)行完畢,然后外層的Do 方法就一直無法釋放鎖,最后就成了死鎖。

錯(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í)行過程中已將持有了該鎖,需要 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è)原子類作為標(biāo)識(shí),加鎖校驗(yàn)和操作原子類,保證只會(huì)被一個(gè)協(xié)程執(zhí)行。

Do 調(diào)用了 doSlow , 在 doSlow 中有defer 關(guān)鍵字,表示執(zhí)行函數(shù)和釋放鎖是倒序執(zhí)行,必須先執(zhí)行完畢 if 判斷和里面的 f() 才能釋放鎖。

到此這篇關(guān)于GoLang中的sync包Once使用執(zhí)行示例的文章就介紹到這了,更多相關(guān)Go sync Once內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

莆田市| 永嘉县| 南乐县| 冀州市| 桦甸市| 汤原县| 泾源县| 军事| 班玛县| 崇左市| 通渭县| 宁武县| 东方市| 泰州市| 井冈山市| 林口县| 任丘市| 甘谷县| 南平市| 盐边县| 吕梁市| 交城县| 海南省| 巩留县| 麦盖提县| 崇左市| 南投市| 新乡市| 郧西县| 普陀区| 锡林郭勒盟| 中超| 济阳县| 无棣县| 精河县| 赤水市| 长乐市| 西林县| 德安县| 当雄县| 丽江市|