自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

曹大帶我學(xué) Go之一調(diào)度的本質(zhì)

開(kāi)發(fā) 后端
熟悉 GMP 模型的朋友都知道,goroutine 最終在 m 上得以執(zhí)行,因?yàn)椴僮飨到y(tǒng)感知不到 goroutine,它只能感知線程,并且線程可以看成是 m。

[[400606]]

你好,我是小X。

曹大最近開(kāi) Go 課程了,小X 正在和曹大學(xué) Go。

這個(gè)系列會(huì)講一些從課程中學(xué)到的讓人醍醐灌頂?shù)臇|西,撥云見(jiàn)日,帶你重新認(rèn)識(shí) Go。

上周課程已經(jīng)開(kāi)始了,曹大直播了第一期,干貨滿滿,大呼過(guò)癮。第一課之后,陸續(xù)又加進(jìn)來(lái)了一些同學(xué)。

首先拋出本文的結(jié)論:Go 調(diào)度的本質(zhì)是一個(gè)生產(chǎn)-消費(fèi)流程。

生產(chǎn)者-消費(fèi)者

生產(chǎn)者-消費(fèi)者模型

我們平時(shí)用 Go 最爽的一點(diǎn)莫過(guò)于用一句 go func(){}() 就啟動(dòng)了一個(gè) goroutine 來(lái)并發(fā)地執(zhí)行任務(wù)。這比用 C/C++ 啟動(dòng)一個(gè)線程并發(fā)地去執(zhí)行任務(wù)方便太多。這句代碼實(shí)際上就生產(chǎn)出了一個(gè) goroutine,并進(jìn)入可運(yùn)行隊(duì)列,等待和 m 來(lái)找它從而可以得到運(yùn)行。

熟悉 GMP 模型的朋友都知道,goroutine 最終在 m 上得以執(zhí)行,因?yàn)椴僮飨到y(tǒng)感知不到 goroutine,它只能感知線程,并且線程可以看成是 m。

所以,m 拿到 goroutine 并運(yùn)行它的過(guò)程就是一個(gè)消費(fèi)過(guò)程。

生產(chǎn)-消費(fèi)過(guò)程

生產(chǎn)過(guò)程——三級(jí)隊(duì)列

生產(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,接下來(lái),它會(huì)以最高優(yōu)先級(jí)得到運(yùn)行,即優(yōu)先被消費(fèi)。

如果 runnext 不為空,那就先負(fù)責(zé)把 runnext 上的 old goroutine 踢走,再把 new goroutine 放上來(lái)。具體踢到哪里呢?又得分情況。

local queue 是一個(gè)大小為 256 的數(shù)組,實(shí)際上用 head 和 tail 指針把它當(dāng)成一個(gè)環(huán)形數(shù)組在使用。如果 local queue 不滿,則將 runnext 放入 local queue;否則,P 的本地隊(duì)列上的 goroutine 太多了,說(shuō)明當(dāng)前 P 的任務(wù)太重了,需要減負(fù),因此需要得到其他 P 協(xié)助。從而,將 runnext 以及當(dāng)前 P 的一半 goroutine 一起打包丟到 global queue 里去。

當(dāng)然,這部分課程里有非常生動(dòng)的動(dòng)畫(huà),這里貼一個(gè)截圖大家感受一下:

生產(chǎn)者動(dòng)畫(huà)

消費(fèi)過(guò)程——調(diào)度循環(huán)

之前的文章里也講到過(guò)調(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)建出來(lái),因此會(huì)有更多的調(diào)度循環(huán)在執(zhí)行。

那邊生產(chǎn)者在不斷地生產(chǎn) g,這邊 m 的調(diào)度循環(huán)不斷地在消費(fèi) g,整個(gè)過(guò)程就 run 起來(lái)了。

找 g 的過(guò)程中當(dāng)然也是從上面的三級(jí)隊(duì)列里找:

先看 runnext,再看 local queue,再看 global queue。當(dāng)然,如果實(shí)在找不到,就去其他 p 去偷。

總結(jié)

今天的文章只用記住一個(gè)觀點(diǎn):Go 調(diào)度的本質(zhì)是一個(gè)生產(chǎn)-消費(fèi)流程。這個(gè)觀點(diǎn)非常新穎,之前我沒(méi)有從哪篇文章看到過(guò),這是曹大自己的感悟。

讀者即使之前沒(méi)見(jiàn)過(guò)類似的說(shuō)法,但是一旦聽(tīng)曹大講出來(lái),就馬上感覺(jué)醍醐灌頂。

 

這種熟悉加意外的效果其實(shí)就是你成長(zhǎng)的時(shí)機(jī)。

 

責(zé)任編輯:武曉燕 來(lái)源: 碼農(nóng)桃花源
相關(guān)推薦

2021-06-10 09:00:32

Go底層代碼

2021-06-07 10:47:02

GoGoexit函數(shù)

2021-06-01 09:27:53

Ast Go語(yǔ)言

2021-08-09 07:47:39

ExtraGoMap

2022-01-05 08:56:20

Go火焰圖編程

2021-07-15 08:58:15

指定配置項(xiàng)Go

2021-05-27 08:59:09

Go匯編命令

2024-12-03 15:15:22

2013-01-09 17:57:11

曹開(kāi)彬

2013-07-02 11:14:40

SCE虛擬化

2022-11-27 23:37:34

Go模式Workspaces

2022-12-14 23:05:29

Go模糊測(cè)試

2020-11-11 08:20:33

比特幣加密貨幣區(qū)塊鏈

2021-10-19 11:22:08

SentinelGo源碼

2014-07-31 10:57:15

Android組件Service

2021-09-26 05:05:46

GoFiber Express

2018-11-16 17:00:05

Python腳本數(shù)據(jù)分析

2022-04-27 10:14:43

進(jìn)程調(diào)度LinuxCPU

2021-07-02 06:54:45

GoJavachannel

2018-11-12 08:04:15

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)