本篇內(nèi)容介紹了“Go語言調(diào)度的本質(zhì)是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
成都創(chuàng)新互聯(lián)公司自2013年創(chuàng)立以來,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元石樓做網(wǎng)站,已為上家服務(wù),為石樓各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108
首先拋出本文的結(jié)論:Go 調(diào)度的本質(zhì)是一個(gè)生產(chǎn)-消費(fèi)流程。
生產(chǎn)者-消費(fèi)者
我們平時(shí)用 Go 最爽的一點(diǎn)莫過于用一句 go func(){}() 就啟動(dòng)了一個(gè) goroutine 來并發(fā)地執(zhí)行任務(wù)。這比用 C/C++ 啟動(dòng)一個(gè)線程并發(fā)地去執(zhí)行任務(wù)方便太多。這句代碼實(shí)際上就生產(chǎn)出了一個(gè) goroutine,并進(jìn)入可運(yùn)行隊(duì)列,等待和 m 來找它從而可以得到運(yùn)行。
熟悉 GMP 模型的朋友都知道,goroutine 最終在 m 上得以執(zhí)行,因?yàn)椴僮飨到y(tǒng)感知不到 goroutine,它只能感知線程,并且線程可以看成是 m。
所以,m 拿到 goroutine 并運(yùn)行它的過程就是一個(gè)消費(fèi)過程。
生產(chǎn)-消費(fèi)過程
生產(chǎn)出的 goroutine 需要找一個(gè)地方存放,這個(gè)地方就是可運(yùn)行隊(duì)列。在 Go 程序中,可運(yùn)行隊(duì)列是分級(jí)的,分為三級(jí):
三級(jí)可運(yùn)行隊(duì)列
runnext 實(shí)際上只能指向一個(gè) goroutine,所以它是一個(gè)特殊的隊(duì)列。
那把 goroutine 放到哪個(gè)可運(yùn)行隊(duì)列呢?看情況。
首先,如果 runnext 為空,那么 goroutine 就會(huì)順利地放入 runnext,接下來,它會(huì)以最高優(yōu)先級(jí)得到運(yùn)行,即優(yōu)先被消費(fèi)。
如果 runnext 不為空,那就先負(fù)責(zé)把 runnext 上的 old goroutine 踢走,再把 new goroutine 放上來。具體踢到哪里呢?又得分情況。
local queue 是一個(gè)大小為 256 的數(shù)組,實(shí)際上用 head 和 tail 指針把它當(dāng)成一個(gè)環(huán)形數(shù)組在使用。如果 local queue 不滿,則將 runnext 放入 local queue;否則,P 的本地隊(duì)列上的 goroutine 太多了,說明當(dāng)前 P 的任務(wù)太重了,需要減負(fù),因此需要得到其他 P 協(xié)助。從而,將 runnext 以及當(dāng)前 P 的一半 goroutine 一起打包丟到 global queue 里去。
當(dāng)然,這部分課程里有非常生動(dòng)的動(dòng)畫,這里貼一個(gè)截圖大家感受一下:
生產(chǎn)者動(dòng)畫
之前的文章里也講到過調(diào)度循環(huán)是咋回事,它實(shí)際上就是 Go 程序在啟動(dòng)的時(shí)候,會(huì)創(chuàng)建和 CPU 核心數(shù)相等個(gè)數(shù)的 P,會(huì)創(chuàng)建初始的 m,稱為 m0。這個(gè) m0 會(huì)啟動(dòng)一個(gè)調(diào)度循環(huán):不斷地找 g,執(zhí)行,再找 g……
偽代碼是這樣的:
調(diào)度循環(huán)
隨著程序的運(yùn)行,m 更多地被創(chuàng)建出來,因此會(huì)有更多的調(diào)度循環(huán)在執(zhí)行。
那邊生產(chǎn)者在不斷地生產(chǎn) g,這邊 m 的調(diào)度循環(huán)不斷地在消費(fèi) g,整個(gè)過程就 run 起來了。
找 g 的過程中當(dāng)然也是從上面的三級(jí)隊(duì)列里找:
先看 runnext,再看 local queue,再看 global queue。當(dāng)然,如果實(shí)在找不到,就去其他 p 去偷。
“Go語言調(diào)度的本質(zhì)是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!