Go語(yǔ)言中g(shù)oroutine的使用
一、什么是 Goroutine ?
在java/c++
中我們要實(shí)現(xiàn)并發(fā)編程的時(shí)候,我們通常需要自己維護(hù)一個(gè)線程池,并且需要自己去包裝一個(gè)又一個(gè)的任務(wù),同時(shí)需要自己去調(diào)度線程執(zhí)行任務(wù)并維護(hù)上下文切換,這一切通常會(huì)耗費(fèi)程序員大量的心智。那么能不能有一種機(jī)制,程序員只需要定義很多個(gè)任務(wù),讓系統(tǒng)去幫助我們把這些任務(wù)分配到CPU
上實(shí)現(xiàn)并發(fā)執(zhí)行呢?
Go
語(yǔ)言中的goroutine
就是這樣一種機(jī)制,goroutine
的概念類(lèi)似于線程,但 goroutine
是由Go的運(yùn)行時(shí)(runtime
)調(diào)度和管理的。Go
程序會(huì)智能地將 goroutine
中的任務(wù)合理地分配給每個(gè)CPU
。Go
語(yǔ)言之所以被稱(chēng)為現(xiàn)代化的編程語(yǔ)言,就是因?yàn)樗谡Z(yǔ)言層面已經(jīng)內(nèi)置了調(diào)度和上下文切換的機(jī)制。
在Go
語(yǔ)言編程中你不需要去自己寫(xiě)進(jìn)程、線程、協(xié)程,你的技能包里只有一個(gè)技能–goroutine
,當(dāng)你需要讓某個(gè)任務(wù)并發(fā)執(zhí)行的時(shí)候,你只需要把這個(gè)任務(wù)包裝成一個(gè)函數(shù),開(kāi)啟一個(gè)goroutine
去執(zhí)行這個(gè)函數(shù)就可以了,就是這么簡(jiǎn)單粗暴。
二、使用 Goroutine
Go
語(yǔ)言中使用goroutine
非常簡(jiǎn)單,只需要在調(diào)用函數(shù)的時(shí)候在前面加上go
關(guān)鍵字,就可以為一個(gè)函數(shù)創(chuàng)建一個(gè)goroutine
。
一個(gè)goroutine
必定對(duì)應(yīng)一個(gè)函數(shù),可以創(chuàng)建多個(gè)goroutine
去執(zhí)行相同的函數(shù)。
單個(gè) goroutine
package main import "fmt" func hello() { fmt.Println("Hello Goroutine!") } func main() { go hello() fmt.Println("main goroutine done!") }
執(zhí)行這段程序:
main goroutine done!
那么問(wèn)題來(lái)了:為什么 Hello Goroutine!
沒(méi)有輸出呢?
在程序啟動(dòng)時(shí),Go
程序就會(huì)為main()
函數(shù)創(chuàng)建一個(gè)默認(rèn)的goroutine
。
當(dāng)main()
函數(shù)返回的時(shí)候該goroutine
就結(jié)束了,所以在main()
函數(shù)中啟動(dòng)的goroutine
會(huì)一同結(jié)束,main
函數(shù)所在的goroutine
就像是權(quán)利的游戲中的夜王,其他的goroutine
都是異鬼,夜王一死它轉(zhuǎn)化的那些異鬼也就全部GG
了。
所以咱們要想辦法讓main
函數(shù)等一等hello
函數(shù),最簡(jiǎn)單粗暴的方式就是time.Sleep
了。
示例:
package main import "fmt" func hello() { fmt.Println("Hello Goroutine!") } func main() { go hello() fmt.Println("main goroutine done!") time.Sleep(time.Second) // 等待1秒 }
執(zhí)行這段程序:
Hello Goroutine!
main goroutine done!
多個(gè) goroutine
package main import "fmt" func hello() { fmt.Println("Hello Goroutine!") } func word() { fmt.Println("Word Goroutine!") } func main() { go hello() go word() fmt.Println("main goroutine done!") time.Sleep(2 * time.Second) // 等待2秒 }
執(zhí)行這段程序:
Hello Goroutine!
Word Goroutine!
main goroutine done!
開(kāi)啟多個(gè) goroutine
只需要再使用一次go
關(guān)鍵字就可以了。
同樣的,咱們?yōu)榱俗屗軌蛲暾敵?,使?time.Sleep
讓main
函數(shù)等待 goroutine
執(zhí)行完成。
sync.WaitGroup 的使用
上面咱們講了如何開(kāi)啟goroutine
,為了goroutine
正常輸出,增加了 time.Sleep
等待。
但在我們實(shí)際項(xiàng)目開(kāi)發(fā)中,生硬的使用time.Sleep
肯定是不合適的。那我們應(yīng)該如何才能正確優(yōu)雅的讓 main
函數(shù)等待 goroutine
執(zhí)行完之后再執(zhí)行呢?
go
語(yǔ)言提供了一個(gè) sync.WaitGroup
的一個(gè)計(jì)數(shù)器的功能。可以用來(lái)優(yōu)雅的實(shí)現(xiàn) goroutine
的正常執(zhí)行和 main
函數(shù)的等待。
示例:
package main import ( "fmt" "sync" ) var wg sync.WaitGroup func hello(){ defer wg.done() // 計(jì)數(shù)器 - 1 fmt.Println("Hello Goroutine!") } func main(){ wg.Add(1) // 計(jì)數(shù)器 + 1 go hello() wg.wait() // 阻塞直到計(jì)數(shù)器變?yōu)? fmt.Println("main goroutine done!") }
執(zhí)行這段程序:
Hello Goroutine!
main goroutine done!
方法名 | 功能 |
---|---|
(wg * WaitGroup) Add(delta int) | 計(jì)數(shù)器+delta |
(wg *WaitGroup) Done() | 計(jì)數(shù)器-1 |
(wg *WaitGroup) Wait() | 阻塞直到計(jì)數(shù)器變?yōu)? |
sync.WaitGroup
內(nèi)部維護(hù)著一個(gè)計(jì)數(shù)器,計(jì)數(shù)器的值可以增加和減少。例如當(dāng)我們啟動(dòng)了 N
個(gè)并發(fā)任務(wù)時(shí),就將計(jì)數(shù)器值增加N
。每個(gè)任務(wù)完成時(shí)通過(guò)調(diào)用Done()
方法將計(jì)數(shù)器減1。通過(guò)調(diào)用Wait()
來(lái)等待并發(fā)任務(wù)執(zhí)行完,當(dāng)計(jì)數(shù)器值為0時(shí),表示所有并發(fā)任務(wù)已經(jīng)完成。
在實(shí)際項(xiàng)目中使用sync.WaitGroup
可以更好的、更優(yōu)雅的控制goroutine
。
三. 結(jié)束語(yǔ)
到此這篇關(guān)于Go語(yǔ)言中g(shù)oroutine的使用的文章就介紹到這了,更多相關(guān)Go語(yǔ)言goroutine內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Go語(yǔ)言Goroutines?泄漏場(chǎng)景與防治解決分析
- Go語(yǔ)言學(xué)習(xí)教程之goroutine和通道的示例詳解
- Go語(yǔ)言使用goroutine及通道實(shí)現(xiàn)并發(fā)詳解
- Go語(yǔ)言中Goroutine的設(shè)置方式
- Go語(yǔ)言中的并發(fā)goroutine底層原理
- Go語(yǔ)言七篇入門(mén)教程四通道及Goroutine
- Go語(yǔ)言之Goroutine與信道異常處理
- Go語(yǔ)言死鎖與goroutine泄露問(wèn)題的解決
- Go語(yǔ)言學(xué)習(xí)之goroutine詳解
- Go語(yǔ)言輕量級(jí)線程Goroutine用法實(shí)例
相關(guān)文章
go實(shí)現(xiàn)thrift的網(wǎng)絡(luò)傳輸性能及需要注意問(wèn)題示例解析
這篇文章主要為大家介紹了go實(shí)現(xiàn)thrift的網(wǎng)絡(luò)傳輸性能及需要注意問(wèn)題示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Go語(yǔ)言基礎(chǔ)學(xué)習(xí)之Context的使用詳解
在Go語(yǔ)言中,Context是一個(gè)非常重要的概念,它用于在不同的?goroutine?之間傳遞請(qǐng)求域的相關(guān)數(shù)據(jù),本文將深入探討Go語(yǔ)言中?Context特性和Context的高級(jí)使用方法,希望對(duì)大家有所幫助2023-05-05