Go并發(fā)編程-線程模型(P)

P(執(zhí)行一個(gè)Go代碼片段所必需的資源)
P是G能夠在M中運(yùn)行的關(guān)鍵蒿赢。Go的運(yùn)行時(shí)系統(tǒng)會(huì)適時(shí)地讓P與不同的M建立或斷開關(guān)聯(lián)伴澄,以使P中的那些可運(yùn)行的G能夠及時(shí)獲得運(yùn)行時(shí)機(jī)吐绵,這與操作系統(tǒng)內(nèi)核在CPU之上實(shí)時(shí)地切換不同的進(jìn)程或線程的情形類似欲账。

改變單個(gè)Go程序間接擁有的P的最大數(shù)量有兩種方法撒汉。

  • 第一種方法轿钠,調(diào)用函數(shù)runtime.GOMAXPROCS并把想要設(shè)定的數(shù)量作為參數(shù)傳入巢钓。
  • 第二種方法,在Go程序運(yùn)行前設(shè)置環(huán)境變量GOMAXPROCS的值谣膳。

P的最大數(shù)量實(shí)際上是對(duì)程序中并發(fā)運(yùn)行的G的規(guī)模的一種限制竿报。P的數(shù)量即為可運(yùn)行G的隊(duì)列的數(shù)量。一個(gè)G在被啟用后继谚,會(huì)先被追加到某個(gè)P的可運(yùn)行G隊(duì)列中烈菌,以等待運(yùn)行時(shí)機(jī)。一個(gè)P只有與一個(gè)M關(guān)聯(lián)在一起時(shí),才會(huì)使其可運(yùn)行G隊(duì)列中的G有機(jī)會(huì)運(yùn)行芽世。
不過挚赊,設(shè)置P的最大數(shù)量只能限制住P的數(shù)量,而對(duì)G和M的數(shù)量沒有任何約束济瓢。當(dāng)M因系統(tǒng)調(diào)用而阻塞(更確切地說荠割,是它運(yùn)行的G進(jìn)入了系統(tǒng)調(diào)用)的時(shí)候,運(yùn)行時(shí)系統(tǒng)會(huì)把該M和與之關(guān)聯(lián)的P分離開來旺矾。這時(shí)蔑鹦,如果這個(gè)P的可運(yùn)行G隊(duì)列中還有未被運(yùn)行的G,那么運(yùn)行時(shí)系統(tǒng)就會(huì)找到一個(gè)空閑M箕宙,或創(chuàng)建一個(gè)新的M嚎朽,并與該P(yáng)關(guān)聯(lián)以滿足這些G的運(yùn)行需要。因此柬帕,M的數(shù)量在很多時(shí)候也都會(huì)比P多哟忍。而G的數(shù)量,一般取決于Go程序本身陷寝。

確定P的最大數(shù)量之后锅很,運(yùn)行時(shí)系統(tǒng)會(huì)根據(jù)這個(gè)數(shù)值重整全局的P列表(runtime. allp)。與全局M列表類似凤跑,該列表中包含了當(dāng)前運(yùn)行時(shí)系統(tǒng)創(chuàng)建的所有P爆安。運(yùn)行時(shí)系統(tǒng)會(huì)把這些P中的可運(yùn)行G全部取出,并放入調(diào)度器的可運(yùn)行G隊(duì)列中饶火。這是調(diào)整全局P列表的一個(gè)重要前提鹏控。被轉(zhuǎn)移的那些G,會(huì)在以后經(jīng)由調(diào)度再次放入某個(gè)P的可運(yùn)行G隊(duì)列肤寝。

與空閑M列表類似当辐,運(yùn)行時(shí)系統(tǒng)中也存在一個(gè)調(diào)度器的空閑P列表(runtime.sched.pidle)。當(dāng)一個(gè)P不再與任何M關(guān)聯(lián)的時(shí)候鲤看,運(yùn)行時(shí)系統(tǒng)就會(huì)把它放入該列表缘揪;而當(dāng)運(yùn)行時(shí)系統(tǒng)需要一個(gè)空閑的P關(guān)聯(lián)某個(gè)M的話,會(huì)從此列表中取出一個(gè)义桂。
注意找筝,P進(jìn)入空閑P列表的一個(gè)前提條件是它的可運(yùn)行G列表必須為空。例如慷吊,在重整全局P列表的時(shí)候袖裕,P在被清空可運(yùn)行G隊(duì)列之后,才會(huì)被放入空閑P列表溉瓶。

與M不同急鳄,P本身是有狀態(tài)的谤民,可能具有的狀態(tài)如下。

  • Pidle: 此狀態(tài)表明當(dāng)前P未與任何M存在關(guān)聯(lián)疾宏。
  • Prunning: 此狀態(tài)表明當(dāng)前P正在與某個(gè)M關(guān)聯(lián)张足。
  • Psyscall: 此狀態(tài)表明當(dāng)前P中的運(yùn)行的那個(gè)G正在進(jìn)行系統(tǒng)調(diào)用。
  • Pgcstop: 此狀態(tài)表明運(yùn)行時(shí)系統(tǒng)需要停止調(diào)度坎藐。例如为牍,運(yùn)行時(shí)系統(tǒng)在開始垃圾回收的某些步驟前,就會(huì)試圖把全局P列表中的所有P都置于此狀態(tài)岩馍。
  • Pdead: 此狀態(tài)表明當(dāng)前P已經(jīng)不會(huì)再被使用碉咆。如果在Go程序運(yùn)行的過程中,通過調(diào)用runtime.GOMAXPROCS函數(shù)減少了P的最大數(shù)量兼雄,那么多余的P就會(huì)被運(yùn)行時(shí)系統(tǒng)置于此狀態(tài)吟逝。

P在創(chuàng)建之初的狀態(tài)是Pgcstop,雖然這并不意味著運(yùn)行時(shí)系統(tǒng)要在這時(shí)進(jìn)行垃圾回收赦肋。不過,P處于這一初始狀態(tài)的時(shí)間會(huì)非常短暫励稳。在緊接著的初始化之后佃乘,運(yùn)行時(shí)系統(tǒng)會(huì)將其狀態(tài)設(shè)置為Pidle,并放入調(diào)度器的空閑P列表驹尼。下圖描繪了P在各個(gè)狀態(tài)之間進(jìn)行流轉(zhuǎn)的具體情況趣避。


P的狀態(tài)轉(zhuǎn)換

可以看到,非Pdead狀態(tài)的P都會(huì)在運(yùn)行時(shí)系統(tǒng)欲停止調(diào)度時(shí)被置于Pgcstop狀態(tài)新翎。不過程帕,等到需要重啟調(diào)度的時(shí)候(如垃圾回收結(jié)束后),它們并不會(huì)被恢復(fù)至原有狀態(tài)地啰,而會(huì)被統(tǒng)一地轉(zhuǎn)換為Pidle狀態(tài)愁拭。也就是說,它們會(huì)被放到同一起跑線上亏吝,并公平地接受再次調(diào)度岭埠。另一方面,非Pgcstop狀態(tài)的P都可能因全局P列表的縮小而被認(rèn)為是多余的蔚鸥,并被置于Pdead狀態(tài)惜论。
不過,我們并不用擔(dān)心其中的G會(huì)失去歸宿止喷。因?yàn)楣堇啵赑被轉(zhuǎn)換為Pdead狀態(tài)之前,其可運(yùn)行G隊(duì)列中的G都會(huì)被轉(zhuǎn)移到調(diào)度器的可運(yùn)行G隊(duì)列弹谁,而它的自由G列表中的G也都會(huì)被轉(zhuǎn)移到調(diào)度器的自由G列表中乾巧。

正如前面所述技羔,每個(gè)P中除了一個(gè)可運(yùn)行G隊(duì)列外,還都包含一個(gè)自由G列表卧抗。這個(gè)列表中包含了一些已經(jīng)運(yùn)行完成的G藤滥。隨著運(yùn)行完成的G的增多,該列表可能會(huì)很長社裆。如果它增長到一定程度拙绊,運(yùn)行時(shí)系統(tǒng)就會(huì)把其中的部分G轉(zhuǎn)移到調(diào)度器的自由G列表中。
另一方面泳秀,當(dāng)使用go語句啟用一個(gè)G的時(shí)候标沪,運(yùn)行時(shí)系統(tǒng)會(huì)先試圖從相應(yīng)P的自由G列表中獲取一個(gè)現(xiàn)成的G,來封裝這個(gè)go語句攜帶的函數(shù)(也稱go函數(shù))嗜傅,僅當(dāng)獲取不到這樣一個(gè)G的時(shí)候才有可能創(chuàng)建一個(gè)新的G金句。考慮到相應(yīng)P的自由G列表為空而獲取不到自由G的情況吕嘀,運(yùn)行時(shí)系統(tǒng)會(huì)在發(fā)現(xiàn)其中的自由G太少時(shí)违寞,預(yù)先嘗試從調(diào)度器的自由G列表中轉(zhuǎn)移過來一些G。如此一來偶房,只有在調(diào)度器的自由G列表也彈盡糧絕的時(shí)候趁曼,才會(huì)有新的G被創(chuàng)建。這在很大程度上提高了G的復(fù)用率棕洋。

在P的結(jié)構(gòu)中挡闰,可運(yùn)行G隊(duì)列和自由G列表是最重要的兩個(gè)成員。至少對(duì)于Go語言的使用者來說是這樣掰盘。它們間接地體現(xiàn)了運(yùn)行時(shí)系統(tǒng)對(duì)G的調(diào)度情況摄悯。

相關(guān)鏈接:
Go并發(fā)編程-線程模型
Go并發(fā)編程-線程模型(M)
Go并發(fā)編程-線程模型(P)
Go并發(fā)編程-線程模型(G)

參考資料:
https://www.ituring.com.cn/book/tupubarticle/16048

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市愧捕,隨后出現(xiàn)的幾起案子奢驯,更是在濱河造成了極大的恐慌,老刑警劉巖晃财,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叨橱,死亡現(xiàn)場離奇詭異,居然都是意外死亡断盛,警方通過查閱死者的電腦和手機(jī)罗洗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钢猛,“玉大人伙菜,你說我怎么就攤上這事∶酰” “怎么了贩绕?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵火的,是天一觀的道長。 經(jīng)常有香客問我淑倾,道長馏鹤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任娇哆,我火速辦了婚禮湃累,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碍讨。我一直安慰自己治力,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布勃黍。 她就那樣靜靜地躺著宵统,像睡著了一般。 火紅的嫁衣襯著肌膚如雪覆获。 梳的紋絲不亂的頭發(fā)上马澈,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音锻梳,去河邊找鬼箭券。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疑枯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛔六,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼荆永,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了国章?” 一聲冷哼從身側(cè)響起具钥,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎液兽,沒想到半個(gè)月后骂删,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡四啰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年宁玫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柑晒。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡欧瘪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匙赞,到底是詐尸還是另有隱情佛掖,我是刑警寧澤妖碉,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站芥被,受9級(jí)特大地震影響欧宜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拴魄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一冗茸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧羹铅,春花似錦蚀狰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至焊切,卻和暖如春扮授,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背专肪。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工刹勃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嚎尤。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓荔仁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親芽死。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乏梁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360