Golang調(diào)度器

原文: http://morsmachine.dk/go-scheduler

為什么在內(nèi)核的線程調(diào)度器之外Go還需要一個(gè)自己的調(diào)度器?

  1. POSIX線程API是對(duì)已有的UNIX進(jìn)程模型的邏輯擴(kuò)展,因此線程和進(jìn)程在很多方面都類似回窘。例如策泣,線程有自己的信號(hào)掩碼俺猿,CPU affinity(進(jìn)程要在某個(gè)給定的 CPU 上盡量長時(shí)間地運(yùn)行而不被遷移到其他處理器的傾向性)乔煞,cgroups褂傀。但是有很多特性對(duì)于Go程序來說都是累贅。 2. 另外一個(gè)問題是基于Go語言模型编检,OS的調(diào)度決定并不一定合理胎食。例如,Go的垃圾回收需要內(nèi)存處于一致性的狀態(tài)蒙谓,這需要所有運(yùn)行的線程都停止斥季。垃圾回收的時(shí)間點(diǎn)是不確定的,如果僅由OS來調(diào)度累驮,將會(huì)由大量的線程停止工作酣倾。
  2. 單獨(dú)開發(fā)一個(gè)Go的調(diào)度器能讓我們知道什么時(shí)候內(nèi)存處于一致性的狀態(tài)。也就是說谤专,當(dāng)開始垃圾回收時(shí)躁锡,運(yùn)行時(shí)只需要為當(dāng)時(shí)正在CPU核上運(yùn)行的那個(gè)線程等待即可,而不是等待所有的線程置侍。

線程模型——高級(jí)語言對(duì)內(nèi)核線程的封裝實(shí)現(xiàn)

  1. N:1模型映之,N個(gè)用戶空間線程在1個(gè)內(nèi)核空間線程上運(yùn)行。優(yōu)勢(shì)是上下文切換非忱唬快但是無法利用多核系統(tǒng)的優(yōu)點(diǎn)杠输。
  2. 1:1模型,1個(gè)內(nèi)核空間線程運(yùn)行一個(gè)用戶空間線程秕衙。這種充分利用了多核系統(tǒng)的優(yōu)勢(shì)但是上下文切換非常慢蠢甲,因?yàn)槊恳淮握{(diào)度都會(huì)在用戶態(tài)和內(nèi)核態(tài)之間切換。(POSIX線程模型(pthread)据忘,Java)
  3. M:N模型鹦牛, 每個(gè)用戶線程對(duì)應(yīng)多個(gè)內(nèi)核空間線程,同時(shí)也可以一個(gè)內(nèi)核空間線程對(duì)應(yīng)多個(gè)用戶空間線程勇吊。Go打算采用這種模型曼追,使用任意個(gè)內(nèi)核模型管理任意個(gè)goroutine。這樣結(jié)合了以上兩種模型的優(yōu)點(diǎn)汉规,但缺點(diǎn)就是調(diào)度的復(fù)雜性礼殊。

Golang的調(diào)度器實(shí)現(xiàn)

Go的調(diào)度器使用了三種結(jié)構(gòu):M,P针史,S

  • M代表內(nèi)核線程晶伦,類似于標(biāo)準(zhǔn)的POSIX線程,M代表machine悟民。
  • G代表goroutine坝辫,它擁有自己的棧,程序計(jì)數(shù)器(instruction counter)和一些關(guān)于goroutine調(diào)度的信息(如正在阻塞的channel)射亏。
  • P代表processor近忙,表示調(diào)度的上下文竭业。可以把它看作是一個(gè)局部的調(diào)度器及舍,讓Go代碼跑在一個(gè)單獨(dú)的線程上未辆。這是讓Go從一個(gè)N:1調(diào)度器映射到一個(gè)M:N調(diào)度器的關(guān)鍵。

如上圖所示锯玛,每個(gè)線程運(yùn)行了一個(gè)goroutine咐柜,所以必須得維持一個(gè)上下文P。

上下文的數(shù)量由啟動(dòng)時(shí)環(huán)境變量$GOMAXPROCS或者是由runtime的方法GOMAXPROCS()決定(默認(rèn)值為1攘残,Go1.5以后默認(rèn)值為CPU的核心數(shù))拙友。這意味著在程序執(zhí)行的任意時(shí)刻都只有$GOMAXPROCS個(gè)goroutine在同時(shí)運(yùn)行。

灰色的goroutine沒有在運(yùn)行歼郭,等待被調(diào)度遗契。它們被維護(hù)在一個(gè)隊(duì)列(runqueues)里。當(dāng)一個(gè)go語句執(zhí)行病曾,就將一個(gè)新的goroutine添加到隊(duì)列尾牍蜂;當(dāng)運(yùn)行當(dāng)前goroutine到調(diào)度點(diǎn)時(shí),就從隊(duì)列中彈出一個(gè)新的goroutine泰涂。

每一個(gè)context擁有一個(gè)局部的runqueue鲫竞。之前版本的Go調(diào)度器只有一個(gè)全局的帶有互斥鎖的runqueue,這樣線程經(jīng)常被阻塞等待其它線程解鎖逼蒙,在多核機(jī)器上性能表現(xiàn)及其差从绘。

之所以要維護(hù)多個(gè)context,是因?yàn)楫?dāng)一個(gè)OS線程被阻塞時(shí)其做,我們可以把contex移到其它的線程中去顶考。

如上圖所示赁还,當(dāng)一個(gè)內(nèi)核線程M0要被阻塞時(shí)妖泄,P將會(huì)去M1上繼續(xù)運(yùn)行。Go的調(diào)度器保證了擁有足夠的線程跑所有的contexts艘策。因?yàn)檫€有在執(zhí)行的goroutine蹈胡,M0會(huì)暫時(shí)掛起。當(dāng)syscall返回時(shí)朋蔫,M0會(huì)嘗試獲取一個(gè)context來運(yùn)行G0罚渐。一般情況下,它會(huì)從其它內(nèi)核線程偷一個(gè)過來驯妄。如果沒有偷到荷并,它會(huì)把G0放到一個(gè)全局的runqueue內(nèi),將自己放回線程池青扔,進(jìn)入睡眠狀態(tài)源织。

當(dāng)contexts運(yùn)行完所有的本地runqueue時(shí)翩伪,它會(huì)從全局runqueue拉取goroutine。contexts也會(huì)周期性檢查全局runqueue是否存在goroutine谈息,以防止全局runqueue中的goroutine餓死缘屹。

這就是為什么Go程序多線程運(yùn)行的原因,即使GOMAXPROCS只有1侠仇。

另外一種情況就是某個(gè)context的goroutine運(yùn)行完了轻姿,全局runqueue也沒有了goroutine,而其它c(diǎn)ontext還有大量goroutine需要運(yùn)行逻炊。這時(shí)候就需要從其它的地方獲取goroutine互亮。如圖所示,context會(huì)嘗試從其它c(diǎn)ontext的runqueue里面偷一半的goroutine余素。這樣就能確保所有的線程都能以最大負(fù)荷運(yùn)行胳挎。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市溺森,隨后出現(xiàn)的幾起案子慕爬,更是在濱河造成了極大的恐慌,老刑警劉巖屏积,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件医窿,死亡現(xiàn)場離奇詭異,居然都是意外死亡炊林,警方通過查閱死者的電腦和手機(jī)姥卢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渣聚,“玉大人独榴,你說我怎么就攤上這事∞戎Γ” “怎么了棺榔?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長隘道。 經(jīng)常有香客問我症歇,道長,這世上最難降的妖魔是什么谭梗? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任忘晤,我火速辦了婚禮,結(jié)果婚禮上激捏,老公的妹妹穿的比我還像新娘设塔。我一直安慰自己,他們只是感情好远舅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布闰蛔。 她就那樣靜靜地躺著竞思,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钞护。 梳的紋絲不亂的頭發(fā)上盖喷,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音难咕,去河邊找鬼课梳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛余佃,可吹牛的內(nèi)容都是我干的暮刃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼爆土,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼椭懊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起步势,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤氧猬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后坏瘩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盅抚,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年倔矾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妄均。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哪自,死狀恐怖丰包,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情壤巷,我是刑警寧澤邑彪,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站隙笆,受9級(jí)特大地震影響锌蓄,放射性物質(zhì)發(fā)生泄漏升筏。R本人自食惡果不足惜撑柔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望您访。 院中可真熱鬧铅忿,春花似錦、人聲如沸灵汪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至峻凫,卻和暖如春渗鬼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荧琼。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國打工譬胎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人命锄。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓堰乔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親脐恩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恒序,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容

  • 概要 本文從幾個(gè)角度入手涮较,描述和學(xué)習(xí)調(diào)度器原理 講解調(diào)度器的基本概念 go語言的作者實(shí)現(xiàn)的C的協(xié)程庫 libtas...
    zengfan閱讀 6,338評(píng)論 0 21
  • http://skoo.me/go/2013/11/29/golang-schedule?hmsr=studygo...
    baboon閱讀 2,260評(píng)論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器呵曹,智...
    卡卡羅2017閱讀 134,672評(píng)論 18 139
  • 正文開始之前先拋出一個(gè)思考:讓一個(gè)靜態(tài)網(wǎng)站滿足海量用戶訪問本質(zhì)上是一個(gè)并行問題還是并發(fā)問題? 并發(fā)的世界 并發(fā)這個(gè)...
    謝培陽閱讀 1,974評(píng)論 3 16
  • Goroutine是Go里的一種輕量級(jí)線程——協(xié)程啡专。相對(duì)線程冲杀,協(xié)程的優(yōu)勢(shì)就在于它非常輕量級(jí),進(jìn)行上下文切換的代價(jià)非...
    witchiman閱讀 4,837評(píng)論 0 9