国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

歡迎光臨散文網(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ó)家法律
安平县| 定陶县| 涪陵区| 桑植县| 诏安县| 淄博市| 甘德县| 玛沁县| 永丰县| 罗山县| 英吉沙县| 光泽县| 浦北县| 日土县| 合作市| 婺源县| 天全县| 安岳县| 东方市| 乌兰县| 樟树市| 阜宁县| 阜新市| 霍林郭勒市| 合肥市| 克东县| 藁城市| 高邑县| 亚东县| 汤阴县| 繁峙县| 福建省| 文化| 贵溪市| 文成县| 新密市| 固始县| 云龙县| 武陟县| 东阳市| 淄博市|