go語言協(xié)程指的是什么

這篇文章主要講解了“go語言協(xié)程指的是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“go語言協(xié)程指的是什么”吧!

公司主營業(yè)務(wù):成都做網(wǎng)站、成都網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出隨州免費(fèi)做網(wǎng)站回饋大家。

在go語言中,協(xié)程(goroutine)是指在后臺中運(yùn)行的輕量級執(zhí)行線程;go協(xié)程是Go中實(shí)現(xiàn)并發(fā)的關(guān)鍵組成部分。Go中提供了一個關(guān)鍵字go來創(chuàng)建一個Go協(xié)程,當(dāng)在函數(shù)或方法的調(diào)用之前添加一個關(guān)鍵字go,這樣就開啟了一個Go協(xié)程,該函數(shù)或者方法就會在這個Go協(xié)程中運(yùn)行。

Go 協(xié)程 (goroutine) 是指在后臺中運(yùn)行的輕量級執(zhí)行線程,go 協(xié)程是 Go 中實(shí)現(xiàn)并發(fā)的關(guān)鍵組成部分。

由于 Go 協(xié)程相對于傳統(tǒng)操作系統(tǒng)中的線程 (thread) 是非常輕量級的,因此對于一個典型的 Go 應(yīng)用來說,有數(shù)以千計(jì)的 Go 協(xié)程并發(fā)運(yùn)行的情形是十分常見的。并發(fā)可以顯著地提升應(yīng)用的運(yùn)行速度,并且可以幫助我們編寫關(guān)注點(diǎn)分離(Separation of concerns,Soc)的代碼。

什么是 Go 協(xié)程?

我們也許在理論上已經(jīng)知曉 Go 協(xié)程是如何工作的,但是在代碼層級上,go 協(xié)程何許物也?其實(shí),go 協(xié)程看起來只是一個與其他眾 Go 協(xié)程并發(fā)運(yùn)行的一個簡單函數(shù)或者方法,但是我們并不能想當(dāng)然地從函數(shù)或者方法中的定義來確定一個 Go 協(xié)程,go 協(xié)程的確定還是要取決于我們?nèi)绾稳フ{(diào)用。

Go 中提供了一個關(guān)鍵字 go 來讓我們創(chuàng)建一個 Go 協(xié)程,當(dāng)我們在函數(shù)或方法的調(diào)用之前添加一個關(guān)鍵字 go,這樣我們就開啟了一個 Go 協(xié)程,該函數(shù)或者方法就會在這個 Go 協(xié)程中運(yùn)行。

舉個簡單的栗子:

go語言協(xié)程指的是什么

在上面的代碼中,我們定義了一個可以在控制臺輸出 Hello World 字符串的 printHello 的函數(shù),在 main 函數(shù)中,我們就像平時那樣調(diào)用 printHello 函數(shù),最終也是理所當(dāng)然地獲得了期望的結(jié)果。

下面,讓我們嘗試從同一個函數(shù)創(chuàng)建 Go 協(xié)程:

go語言協(xié)程指的是什么

根據(jù) Go 協(xié)程的語法,我們在函數(shù)調(diào)用的前面增加了一個 go 關(guān)鍵字,之后程序運(yùn)行正常,輸出了以下的結(jié)果:

main execution started
main execution stopped

奇怪的是,Hello World 并沒有如同我們預(yù)料的那樣輸出,這期間究竟發(fā)生了什么?

go 協(xié)程總是在后臺運(yùn)行,當(dāng)一個 Go 協(xié)程執(zhí)行的時候(在這個例子中是 go printHello()), Go 并不會像在之前的那個例子中在執(zhí)行 printHello 中的功能時阻塞 main 函數(shù)中剩下語句的執(zhí)行,而是直接忽略了 Go 協(xié)程的返回并繼續(xù)執(zhí)行 main 函數(shù)剩下的語句。即便如此,我們?yōu)槭裁礇]法看到函數(shù)的輸出呢?

在默認(rèn)情況下,每個獨(dú)立的 Go 應(yīng)用運(yùn)行時就創(chuàng)建了一個 Go 協(xié)程,其 main 函數(shù)就在這個 Go 協(xié)程中運(yùn)行,這個 Go 協(xié)程就被稱為 go 主協(xié)程(main Goroutine,下面簡稱主協(xié)程)。在上面的例子中,主協(xié)程 中又產(chǎn)生了一個 printHello 這個函數(shù)的 Go 協(xié)程,我們暫且叫它 printHello 協(xié)程 吧,因而我們在執(zhí)行上面的程序的時候,就會存在兩個 Go 協(xié)程(mainprintHello)同時運(yùn)行。正如同以前的程序那樣,go 協(xié)程們會進(jìn)行協(xié)同調(diào)度。因此,當(dāng) 主協(xié)程 運(yùn)行的時候,Go 調(diào)度器在 主協(xié)程 執(zhí)行完之前并不會將控制權(quán)移交給 printHello 協(xié)程。不幸的是,一旦 主協(xié)程 執(zhí)行完畢,整個程序會立即終止,調(diào)度器再也沒有時間留給 printHello 協(xié)程 去運(yùn)行了。

但正如我們從其他課程所知,通過阻塞條件,我們可以手動將控制權(quán)轉(zhuǎn)移給其他的 Go 協(xié)程 , 也可以說是告訴調(diào)度器讓它去調(diào)度其他可用空閑的 Go 協(xié)程。讓我們調(diào)用 time.Sleep() 函數(shù)去實(shí)現(xiàn)它吧。

go語言協(xié)程指的是什么

如上圖所示,我們修改了程序,程序在 main 函數(shù)的最后一條語句之前調(diào)用了 time.Sleep(10 * time.Millisecond),使得 主協(xié)程 在執(zhí)行最后一條指令之前調(diào)度器就將控制權(quán)轉(zhuǎn)移給了 printhello 協(xié)程。在這個例子中,我們通過調(diào)用 time.Sleep(10 * time.Millisecond) 強(qiáng)行讓 主協(xié)程 休眠 10ms 并且在在這個 10ms 內(nèi)不會再被調(diào)度器重新調(diào)度運(yùn)行。

一旦 printHello 協(xié)程 執(zhí)行,它就會向控制臺打印‘ Hello World !’,然后該 Go 協(xié)程(printHello 協(xié)程)就會隨之終止,接下來 主協(xié)程 就會被重新調(diào)度(因?yàn)?main Go 協(xié)程已經(jīng)睡夠 10ms 了),并執(zhí)行最后一條語句。因此,運(yùn)行上面的程序就會得到以下的輸出 :

main execution started
Hello World!
main execution stopped

下面我稍微修改一下例子,我在 printHello 函數(shù)的輸出語句之前添加了一條 time.Sleep(time.Millisecond)。我們已經(jīng)知道了如果我們在函數(shù)中調(diào)用了休眠(sleep)函數(shù),這個函數(shù)就會告訴 Go 調(diào)度器去調(diào)度其他可被調(diào)度的 Go 協(xié)程。在上一課中提到,只有非休眠(non-sleeping)的 Go 協(xié)程才會被認(rèn)為是可被調(diào)度的,所以主協(xié)程在這休眠的 10ms 內(nèi)是不會被再次調(diào)度的。因此 主協(xié)程 先打印出“ main execution started ” 接著就創(chuàng)建了一個 printHello協(xié)程,需要注意此時的 主協(xié)程 還是非休眠狀態(tài)的,在這之后主協(xié)程就要調(diào)用休眠函數(shù)去睡 10ms,并且把這個控制權(quán)讓出來給printHello協(xié)程。printHello協(xié)程會先休眠 1ms 告訴調(diào)度器看看有沒有其他可調(diào)度的 Go 協(xié)程,在這個例子里顯然沒有其他可調(diào)度的 Go 協(xié)程了,所以在printHello協(xié)程結(jié)束了這 1ms 的休眠戶就會被調(diào)度器調(diào)度,接著就輸出了“ Hello World ”字符串,之后這個 Go 協(xié)程運(yùn)行結(jié)束。之后,主協(xié)程會在之后的幾毫秒被喚醒,緊接著就會輸出“ main execution stopped ”并且結(jié)束整個程序。

go語言協(xié)程指的是什么

上面的程序依舊和之前的例子一樣,輸出以下相同的結(jié)果:

main execution started
Hello World!
main execution stopped

要是,我把這個printHello協(xié)程中的休眠 1 毫秒改成休眠 15 毫秒,這個結(jié)果又是如何呢?

go語言協(xié)程指的是什么

在這個例子中,與其他的例子最大的區(qū)別就是printHello協(xié)程比主協(xié)程的休眠時間還要長,很明顯,主協(xié)程要比 printHello 協(xié)程喚醒要早,這樣的結(jié)果就是主協(xié)程即使喚醒后執(zhí)行完所有的語句,printHello 協(xié)程還是在休眠狀態(tài)。之前提到過,主協(xié)程比較特殊,如果主協(xié)程執(zhí)行結(jié)束后整個程序就要退出,所以 printHello 協(xié)程得不到機(jī)會去執(zhí)行下面的輸出的語句了,所以以上的程序的數(shù)據(jù)結(jié)果如下:

main execution started
main execution stopped

使用多 Go 協(xié)程

就像之前我所提到過的,你可以隨心所欲地創(chuàng)建多個 Go 協(xié)程。下面讓我們定義兩個簡單的函數(shù),一個是用于順序打印某個字符串中的每個字符,另一個是順序打印出某個整數(shù)切片中的每個數(shù)字。

go語言協(xié)程指的是什么

在上圖中的程序中,我們連續(xù)地創(chuàng)建了兩個 Go 協(xié)程,程序輸出的結(jié)果如下:

main execution started
H e l l o 1 2 3 4 5
main execution stopped

上面的結(jié)果證實(shí)了 Go 協(xié)程是以合作式調(diào)度來運(yùn)作的。下面我們在每個函數(shù)中的輸出語句的下面添加一行 time.Sleep,讓函數(shù)在輸出每個字符或數(shù)字后休息一段時間,好讓調(diào)度器調(diào)度其他可用的 Go 協(xié)程。

go語言協(xié)程指的是什么

在上面的程序中,我又修改了一下輸出語句使得我們可以看到每個字符或數(shù)字的輸出時刻。理論上主協(xié)程會休眠 200ms,因此其他 Go 協(xié)程要趕在主協(xié)程喚醒之前做完自己的工作,因?yàn)橹鲄f(xié)程喚醒之后就會導(dǎo)致程序退出。getChars 協(xié)程每打印一個字符就會休眠 10ms,之后控制權(quán)就會傳給 getDigits 協(xié)程,getDigits 協(xié)程每打印一個數(shù)字后就休眠 30ms,若 getChars 協(xié)程喚醒,則會把控制權(quán)傳回 getChars 協(xié)程,如此往復(fù)。在代碼中可以看到,getChars 協(xié)程會在其他協(xié)程休眠的時候多次進(jìn)行打印字符以及休眠操作,所以我們預(yù)計(jì)可以看到輸出的字符比數(shù)字更具有連續(xù)性。

我們在 Windows 上運(yùn)行上面的程序,得到了以下的結(jié)果:

main execution started at time 0s
H at time 1.0012ms                         <-|
1 at time 1.0012ms                           | almost at the same time
e at time 11.0283ms                        <-|
l at time 21.0289ms                          | ~10ms apart
l at time 31.0416ms
2 at time 31.0416ms
o at time 42.0336ms
3 at time 61.0461ms                        <-|
4 at time 91.0647ms                          |
5 at time 121.0888ms                         | ~30ms apart
main execution stopped at time 200.3137ms    | exiting after 200ms

通過以上輸出結(jié)果可以證明我們之前對輸出的討論。對于這個結(jié)果,我們可以通過下面的的程序運(yùn)行圖來解釋。需要注意的是,我們在圖中定義一個輸出語句大約會花費(fèi) 1ms 的 CPU 時間,而這個時間相對于 200ms 來說是可以忽略不計(jì)的。

go語言協(xié)程指的是什么

現(xiàn)在我們已經(jīng)知道了如何去創(chuàng)建 Go 協(xié)程以及去如何去使用它。但是使用 time.Sleep 只是一個讓我們獲取理想結(jié)果的一個小技巧。在實(shí)際生產(chǎn)環(huán)境中,我們無法知曉一個 Go 協(xié)程到底需要執(zhí)行多長的時間,因而在 main 函數(shù)里面添加一個 time.Sleep 并不是一個解決問題的方法。我們希望 Go 協(xié)程在執(zhí)行完畢后告知主協(xié)程運(yùn)行的結(jié)果。在目前階段,我們還不知道如何向其他 Go 協(xié)程傳遞以及獲取數(shù)據(jù),簡而言之,就是與其他 Go 協(xié)程進(jìn)行通信。這就是 channels 引入的原因。我們會在下一次課中討論這個東西。

匿名 Go 協(xié)程

如果一個匿名函數(shù)可以退出,那么匿名 Go 協(xié)程也同樣可以退出。請參照functions課程中的 即時調(diào)用函數(shù)(Immedietly invoked function) 來理解本節(jié)。讓我們修改一下之前 printHello 協(xié)程的例子:

go語言協(xié)程指的是什么

結(jié)果非常明顯,因?yàn)槲覀兌x了匿名函數(shù),并在同一語句中作為 Go 協(xié)程執(zhí)行。

需要注意的是,所有的 Go 協(xié)程都是匿名的,因?yàn)槲覀儚?strong>并發(fā)(concurrency一課中學(xué)到,go 協(xié)程是不存在標(biāo)識符的,在這里所謂的匿名 Go 協(xié)程只是通過匿名函數(shù)來創(chuàng)建的 Go 協(xié)程罷了。

感謝各位的閱讀,以上就是“go語言協(xié)程指的是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對go語言協(xié)程指的是什么這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

新聞標(biāo)題:go語言協(xié)程指的是什么
網(wǎng)站鏈接:http://muchs.cn/article48/gjsehp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站網(wǎng)站排名、做網(wǎng)站、定制開發(fā)、搜索引擎優(yōu)化、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司