Go語言并發(fā)編程的核心 —— GMP調(diào)度模型

在Go語言中砖茸,GMP調(diào)度模型是實現(xiàn)并發(fā)的重要手段之一堰怨。GMP調(diào)度模型的核心思想是將M(Machine)二鳄、G(Goroutine)和P(Processor)三個概念分離開來奥溺,通過調(diào)度器來協(xié)調(diào)它們之間的關系好港,從而實現(xiàn)高效的并發(fā)愉镰。

M(Machine)

M代表著操作系統(tǒng)中的線程,它是Go語言中的執(zhí)行單位钧汹。在程序啟動時丈探,Go語言會創(chuàng)建一定數(shù)量的M,每個M都會綁定一個P拔莱。M的數(shù)量默認是CPU核心數(shù)碗降,但是可以通過GOMAXPROCS環(huán)境變量來設置。

G(Goroutine)

Goroutine是Go語言中的輕量級線程塘秦,它可以與M一起調(diào)度執(zhí)行讼渊。在程序中,我們可以通過關鍵字go來啟動一個Goroutine尊剔,例如:

go func() {
    // 處理業(yè)務邏輯
}()

在上面的例子中爪幻,我們使用go關鍵字啟動了一個Goroutine,并在其中執(zhí)行業(yè)務邏輯须误。需要注意的是挨稿,Goroutine是由Go語言的運行時(runtime)進行調(diào)度的,而不是由操作系統(tǒng)進行調(diào)度京痢,因此它具有輕量級奶甘、高效等特點。

P(Processor)

Processor是Go語言中的處理器祭椰,它負責將Goroutine分配給M執(zhí)行臭家。每個M都會綁定一個P,而P的數(shù)量可以通過runtime.NumCPU()來獲确接佟(不同于M的數(shù)量)侣监。

調(diào)度器

調(diào)度器是GMP調(diào)度模型的核心,它負責將Goroutine分配給M執(zhí)行臣淤,并在M的數(shù)量不足時創(chuàng)建新的M橄霉。調(diào)度器還可以將M從一個P轉(zhuǎn)移到另一個P,以達到負載均衡的目的。

調(diào)度器的實現(xiàn)方式比較復雜姓蜂,但是它的工作原理可以簡單概括如下:

  • 當一個Goroutine被啟動時按厘,它會被放入一個全局的運行隊列中(稱為全局隊列)。
  • 當一個M空閑時钱慢,它會從全局隊列中獲取一個Goroutine逮京,并開始執(zhí)行它。
  • 當一個Goroutine阻塞時束莫,它會被放入一個本地的等待隊列中(稱為本地隊列)懒棉。
  • 當一個M中的本地隊列為空時,它會從全局隊列中獲取一批Goroutine览绿,并將它們放入本地隊列中策严。
  • 當一個P中的本地隊列為空時,它會從其他P中的本地隊列中獲取一批Goroutine饿敲,并將它們放入本地隊列中妻导。
  • 當一個M執(zhí)行時間過長時,調(diào)度器會中斷它的執(zhí)行怀各,并將它的狀態(tài)保存到一個全局的掛起隊列中倔韭。下次該M被分配到執(zhí)行時,它會從掛起隊列中恢復狀態(tài)瓢对,并繼續(xù)執(zhí)行寿酌。
  • 當一個M執(zhí)行的Goroutine數(shù)量達到一定閾值時,調(diào)度器會將它的狀態(tài)保存到一個全局的休眠隊列中硕蛹。下次該M被分配到執(zhí)行時醇疼,它會從休眠隊列中恢復狀態(tài),并繼續(xù)執(zhí)行妓美。

下面我們來看一個簡單的示例,它通過啟動多個Goroutine來計算斐波那契數(shù)列的值:

package main

import "fmt"

func main() {
    for i := 0; i < 10; i++ {
        go func() {
            fmt.Println(fib(40))
        }()
    }
}

func fib(n int) int {
    if n < 2 {
        return n
    }
    return fib(n-1) + fib(n-2)
}

在上面的例子中鲤孵,我們啟動了10個Goroutine壶栋,并在其中計算斐波那契數(shù)列的值。由于斐波那契數(shù)列的計算是CPU密集型的普监,因此這個程序會利用GMP調(diào)度模型來實現(xiàn)高效的并發(fā)贵试。

注意事項

在使用GMP調(diào)度模型時,需要注意以下幾點:

  • 不要在Goroutine中阻塞或者進行長時間的計算凯正,這會導致M被掛起或者休眠毙玻,從而影響程序的性能。
  • 不要在Goroutine中訪問共享資源時不加鎖廊散,這會導致數(shù)據(jù)競爭桑滩,從而引發(fā)難以排查的bug。
  • 不要將過多的Goroutine放入全局隊列中允睹,這會導致調(diào)度器的性能下降运准,從而影響程序的性能幌氮。
  • 不要將過多的M創(chuàng)建出來,這會導致系統(tǒng)資源的浪費胁澳,從而影響程序的性能该互。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市韭畸,隨后出現(xiàn)的幾起案子宇智,更是在濱河造成了極大的恐慌,老刑警劉巖胰丁,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件随橘,死亡現(xiàn)場離奇詭異,居然都是意外死亡隘马,警方通過查閱死者的電腦和手機太防,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酸员,“玉大人蜒车,你說我怎么就攤上這事♂`拢” “怎么了酿愧?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邀泉。 經(jīng)常有香客問我嬉挡,道長,這世上最難降的妖魔是什么汇恤? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任庞钢,我火速辦了婚禮,結(jié)果婚禮上因谎,老公的妹妹穿的比我還像新娘基括。我一直安慰自己,他們只是感情好财岔,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布风皿。 她就那樣靜靜地躺著,像睡著了一般匠璧。 火紅的嫁衣襯著肌膚如雪桐款。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天夷恍,我揣著相機與錄音魔眨,去河邊找鬼。 笑死,一個胖子當著我的面吹牛冰沙,可吹牛的內(nèi)容都是我干的侨艾。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼拓挥,長吁一口氣:“原來是場噩夢啊……” “哼唠梨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起侥啤,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤当叭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盖灸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚁鳖,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年赁炎,在試婚紗的時候發(fā)現(xiàn)自己被綠了醉箕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡徙垫,死狀恐怖讥裤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情姻报,我是刑警寧澤己英,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站吴旋,受9級特大地震影響损肛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜荣瑟,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一治拿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笆焰,春花似錦劫谅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鳄梅。三九已至叠国,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戴尸,已是汗流浹背粟焊。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人项棠。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓悲雳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親香追。 傳聞我的和親對象是個殘疾皇子合瓢,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

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