最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

你知道 GO 中的 協(xié)程可以無(wú)止境的開(kāi)嗎?

2023-02-21 23:02 作者:阿兵云原生  | 我要投稿

GO語(yǔ)言天生高并發(fā)的語(yǔ)言,那么是不是使用 go 開(kāi)辟協(xié)程越多越好的,那么在 go 里面,協(xié)程是不是可以開(kāi)無(wú)限多個(gè)呢?

那么我們就一起來(lái)看看嘗試寫(xiě)寫(xiě) demo 吧

嘗試開(kāi)辟盡可能多的 協(xié)程

寫(xiě)一個(gè) demo ,循環(huán)開(kāi) 1 << 31 - 1 個(gè)協(xié)程看看會(huì)是什么效果

func?main()?{
?goroutineNum?:=?math.MaxInt32

?for?i?:=?0;?i?<?goroutineNum;?i++?{
??go?func(i?int)?{
???fmt.Println("?i?==?",?i,?"func?==?",?runtime.NumGoroutine())
??}(i)
?}
}

執(zhí)行后,我人都傻了,直接是沒(méi)有輸出,2 核 1 G 的服務(wù)器直接卡死 , 感興趣的 xdm 可以嘗試一波

這里說(shuō)一下,出現(xiàn)上述現(xiàn)象的原因是:

我們迅速的瘋狂開(kāi)辟協(xié)程,又不控制并發(fā)數(shù)量,那么在那段很短的時(shí)間里面,go 程序會(huì)盡可能多的占用操作系統(tǒng)資源,直到被操作系統(tǒng)主動(dòng)殺掉

一旦主協(xié)程被殺掉,那么其他的協(xié)程也全部 game over , 因?yàn)樗麄冋加玫馁Y源是用戶態(tài)的共享資源,一個(gè)協(xié)程掛掉,是會(huì)影響到其他協(xié)程的

嘗試控制協(xié)程數(shù)量

咱們實(shí)現(xiàn)的方法是,使用 channel ,設(shè)置 channel 的緩沖個(gè)數(shù)來(lái)控制實(shí)際并發(fā)的協(xié)程個(gè)數(shù),一起來(lái)看看是否有效果

func?processGo(i?int,?ch?chan?struct{})?{
?fmt.Println("?i?==?",?i,?"func?==?",?runtime.NumGoroutine())
?<-ch
}

func?main()?{
?goroutineNum?:=?math.MaxInt32

?ch?:=?make(chan?struct{},?5)

?for?i?:=?0;?i?<?goroutineNum;?i++?{
??ch?<-?struct{}{}
??go?processGo(i,?ch)

?}
}

效果見(jiàn)如下截圖,由于數(shù)據(jù)打印太長(zhǎng),如下為部分?jǐn)?shù)據(jù)

這里我們可以看到,加入并發(fā)控制后,效果還是很明顯的,至少我的服務(wù)器不會(huì)被卡死了

通過(guò)打印我們可以看出來(lái),總共 6 個(gè)協(xié)程,其中有 5 個(gè)是子協(xié)程,1 個(gè)是主協(xié)程

我們這里,使用 channel 的方式來(lái)控制并發(fā),go 協(xié)程的創(chuàng)建速度 依賴于 for 循環(huán)的速度,而 for 循環(huán)的速度是被 channel 控制住了 ,channel 的速度實(shí)際上又被實(shí)際處理事情的協(xié)程的處理速度控制著,因此,我們可以保證在同一個(gè)時(shí)間內(nèi),并發(fā)運(yùn)行的協(xié)程總共是 6 個(gè)

但是這就夠了么, nonono , 我們可以再來(lái)看一個(gè)例子

  • 我們?cè)O(shè)置在循環(huán)的個(gè)數(shù)為 10 ,比剛才的值小了很多,代碼邏輯保持一致

func?main()?{
?goroutineNum?:=?10

?ch?:=?make(chan?struct{},?5)

?for?i?:=?0;?i?<?goroutineNum;?i++?{
??ch?<-?struct{}{}
??go?processGo(i,?ch)

?}
}

執(zhí)行程序看效果

#?go?run?main.go
?i?==??4?func?==??6
?i?==??5?func?==??6
?i?==??6?func?==??6
?i?==??7?func?==??6
?i?==??8?func?==??6

我們發(fā)現(xiàn)輸出并不是我們想要的 , 出現(xiàn)這個(gè)的原因是主協(xié)程 循環(huán) 10 次完畢之后,就會(huì)馬上退出程序,進(jìn)而子協(xié)程也隨之退出,這個(gè)問(wèn)題需要解決

嘗試加入 sync 同步機(jī)制,讓主協(xié)程等一下子協(xié)程

之前我們有分享到 go 中的一個(gè)知識(shí)點(diǎn),可以使用 sync 來(lái)一起控制同步 , 就是使用 sync.WaitGroup ,不知道 xdm 是否還記得,不記得沒(méi)關(guān)系,咱們今天再使用一遍,看看效果

  • 加入 sync 機(jī)制,循環(huán)的時(shí)候,需要開(kāi)辟協(xié)程時(shí),則 sync.Add

  • 協(xié)程結(jié)束的時(shí)候,sync.Done

  • 主協(xié)程循環(huán)完畢之后,等待子協(xié)程完成自己的事情,使用 sync.Wait

func?processGo(i?int,?ch?chan?struct{})?{
?fmt.Println("?i?==?",?i,?"func?==?",?runtime.NumGoroutine())
?<-ch
?wg.Done()
}

var?wg?=?sync.WaitGroup{}

func?main()?{
?goroutineNum?:=?10

?ch?:=?make(chan?struct{},?5)

?for?i?:=?0;?i?<?goroutineNum;?i++?{
??ch?<-?struct{}{}
??wg.Add(1)
??go?processGo(i,?ch)

?}

?wg.Wait()
}

上述代碼中,我們可以簡(jiǎn)單理解 sync 的使用, sync.Add 就是添加需要等待多少個(gè)子協(xié)程結(jié)束, sync.Done 就是當(dāng)前的子協(xié)程結(jié)束了,減去 1 個(gè)協(xié)程, sync.Wait 就是等待 子協(xié)程的個(gè)數(shù)最終變成 0 ,則認(rèn)為子協(xié)程全部關(guān)閉

運(yùn)行程序來(lái)查看效果

m#?go?run?main.go
?i?==??4?func?==??6
?i?==??5?func?==??6
?i?==??6?func?==??6
?i?==??7?func?==??6
?i?==??8?func?==??6
?i?==??9?func?==??6
?i?==??0?func?==??5
?i?==??1?func?==??4
?i?==??2?func?==??3
?i?==??3?func?==??2

嘗試做的更加可控一些更加優(yōu)秀一些

我們可以思考一下,上面的邏輯是不停的有協(xié)程在創(chuàng)建,也不停的有協(xié)程在被銷毀,這樣還是很耗資源的,我們是否可以固定設(shè)置具體的協(xié)程在做事情,并且將發(fā)送數(shù)據(jù)和處理數(shù)據(jù)進(jìn)行一個(gè)分離呢?

就類似于生產(chǎn)者和消費(fèi)者一樣

咱們來(lái)嘗試寫(xiě)一個(gè) demo

  • 專門(mén)寫(xiě)一個(gè)函數(shù)用于分發(fā)任務(wù)

  • 分發(fā)任務(wù)之前先開(kāi)辟好對(duì)應(yīng)的協(xié)程,等待任務(wù)進(jìn)來(lái)

func?processGo(i?int,?ch?chan?struct{})?{
?for?data?:=?range?ch?{
??fmt.Println("?i?==?",?data,?"func?==?",?runtime.NumGoroutine())
??wg.Done()
?}
}

func?distributeTask(ch?chan?struct{})?{
?wg.Add(1)
?ch?<-?struct{}{}
}

var?wg?=?sync.WaitGroup{}

func?main()?{
?goroutineNum?:=?2
?taskNum?:=?math.MaxInt32

?ch?:=?make(chan?struct{})

?//?先開(kāi)辟好協(xié)程?等待處理數(shù)據(jù)
?for?i?:=?0;?i?<?goroutineNum;?i++?{
??go?processGo(i,?ch)
?}

?//?分發(fā)事項(xiàng)
?for?i?:=?0;?i?<?taskNum;?i++?{
??distributeTask(ch)
?}

?wg.Wait()
}

此處使用 sync 控制的同步,可以說(shuō)是 對(duì)應(yīng)的是任務(wù)數(shù)量, 主協(xié)程是等待所有分發(fā)的任務(wù)數(shù)都被完成了,主協(xié)程才關(guān)閉程序

執(zhí)行程序查看效果

?go?run?main.go

程序正常運(yùn)行沒(méi)有毛病,這樣做的話,我們可以將分發(fā)任務(wù)和處理任務(wù)進(jìn)行分離,還大大減少了不必要的協(xié)程切換

對(duì)于如上案例做一個(gè)比喻

channel + sync 的案例 :

最上面的第一種案例,就是相當(dāng)于動(dòng)態(tài)雇傭 5 個(gè)工人,有任務(wù)的時(shí)候,工人就上去做,做完了自己下崗就得了,反正我這里只容納 5 個(gè)工人,且每個(gè)工人做完 1 個(gè)任務(wù)就得走

分發(fā)任務(wù)和處理數(shù)據(jù)的任務(wù)分離案例 :

最后的這個(gè)案例,就是固定的雇傭 2 個(gè)工人干活,項(xiàng)目經(jīng)理就不停的扔任務(wù)進(jìn)行來(lái),這倆人就瘋狂的干

xdm ,go 里面不能濫用協(xié)程,需要控制好 go 協(xié)程的數(shù)量

歡迎點(diǎn)贊,關(guān)注,收藏

朋友們,你的支持和鼓勵(lì),是我堅(jiān)持分享,提高質(zhì)量的動(dòng)力

好了,本次就到這里

技術(shù)是開(kāi)放的,我們的心態(tài),更應(yīng)是開(kāi)放的。擁抱變化,向陽(yáng)而生,努力向前行。

我是阿兵云原生,歡迎點(diǎn)贊關(guān)注收藏,下次見(jiàn)~


你知道 GO 中的 協(xié)程可以無(wú)止境的開(kāi)嗎?的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
阿拉善右旗| 宣化县| 方正县| 岳西县| 陈巴尔虎旗| 民权县| 昌都县| 盐边县| 武汉市| 邻水| 鹤庆县| 开化县| 屏边| 汤原县| 镶黄旗| 临泽县| 定南县| 高雄市| 富顺县| 陕西省| 观塘区| 华蓥市| 乐业县| 兰西县| 丰宁| 六安市| 涟水县| 沅江市| 黄陵县| 蓬莱市| 沙洋县| 甘谷县| 三原县| 曲阳县| 奉贤区| 湄潭县| 平原县| 仙游县| 齐河县| 张家港市| 连山|