golang 排程學習 綜述

2021-09-24 14:04:12 字數 2453 閱讀 2197

本文將會描述golang排程的大致方式,並介紹後文中將會用到的一些資料結構,及實現原理

注:這本是給自己學習用的筆記,其中包含一些網上大牛的資料節選片段,也忘了出處,求海涵。大佬不願意可以聯絡刪除謝謝。

主要參考:《go語言學習筆記》

一般多執行緒會有以下幾種執行緒模型:

go採用方案:採用兩級(混合型)執行緒模型,通過m:n的排程器去獲取這兩個世界的全部優勢,在任意數目的os執行緒上呼叫任意數目的goroutines。

golang 排程模型架構如下圖:

在golang的原始碼結構中,排程過程可用下圖展示:

結合兩個圖我們可以分析出幾個結論:

我們通過 go func()來建立乙個goroutine;

有兩個儲存goroutine的佇列,乙個是區域性排程器p的local queue(當p繫結的時候m的時候,可以無鎖分配記憶體和無鎖訪問任務佇列)、乙個是全域性排程器資料模型schedt的global queue。新建立的goroutine會先儲存在local queue,如果local queue已經滿了就會儲存在全域性的global queue;

goroutine只能執行在m中,乙個m必須持有乙個p,m與p是1:1的關係。m會從p的local queue彈出乙個runable狀態的goroutine來執行,如果p的local queue為空,就會執行work stealing;

乙個m排程goroutine執行的過程是乙個loop;

當m執行某乙個goroutine時候如果發生了syscall或則其餘阻塞操作,m會阻塞,如果當前有一些g在執行,runtime會把這個執行緒m從p中摘除(detach),然後再建立乙個新的作業系統的執行緒(如果有空閒的執行緒可用就復用空閒執行緒)來服務於這個p;

當系統呼叫結束時候,這個goroutine會嘗試獲取乙個空閒的p執行,並放入到這個p的local queue。如果獲取不到p,那麼這個執行緒m會park它自己(休眠), 加入到空閒執行緒中,然後這個goroutine會被放入schedt的global queue。

gpm簡介(具體結構見下文資料結構):

下文介紹排程其中會使用到的部分基本資料結構,原始碼中的資料結構在runtime包中的runtime2.go中

stack 描述了go執行堆疊。堆疊的邊界正好是 [lo,hi),兩邊都沒有隱式資料結構。

type stack struct

g 的執行現場,建立時初始化,用來儲存g當前的執行狀況,g被搶占是會儲存當前現場,下次排程的時候從這裡恢復

type gobuf struct

type g struct

g裡面比較重要的成員如下

g的狀態:

當 g 遇到阻塞,或需要等待的場景時,會被打包成 sudog 這樣乙個結構。乙個 g 可能被打包為多個 sudog 分別掛在不同的等待佇列上:

// sudog 代表在等待列表裡的 g,比如向 channel 傳送/接收內容時

// 之所以需要 sudog 是因為 g 和同步物件之間的關係是多對多的

// 乙個 g 可能會在多個等待佇列中,所以乙個 g 可能被打包為多個 sudog

// 多個 g 也可以等待在同乙個同步物件上

// 因此對於乙個同步物件就會有很多 sudog 了

// sudog 是從乙個特殊的池中進行分配的。用 acquiresudog 和 releasesudog 來分配和釋放 sudog

type sudog struct

執行緒在 runtime 中的結構,對應乙個 pthread,pthread 也會對應唯一的核心執行緒(task_struct):

type m struct

m裡面比較重要的成員如下

m並沒有像g和p一樣的狀態標記, 但可以認為乙個m有以下的狀態:

m可以執行兩種**:

自旋中(spinning)這個狀態非常重要, 是否需要喚醒或者建立新的m取決於當前自旋中的m的數量.通常建立乙個m的原因是由於沒有足夠的m來關聯p並執行其中可執行的g。而且執行時系統執行系統監控的時候,或者gc的時候也會建立m。

抽象資料結構,可以認為是 processor 的抽象,代表了任務執行時的上下文,m 必須獲得 p 才能執行:

type p struct

p裡面比較重要的成員如下

p的狀態

全域性排程器,全域性只有乙個 schedt 型別的例項:

type schedt struct

sap生產排程綜述

sap生產排程綜述 文章摘要 sap生產排程綜述 做什麼都需要計畫,製造企業的生產更是如此。企業做出銷售 或是接到客戶訂單時,必須快速做出反映,能不能在要求的期間內完成訂單,在什麼時候完成,完成訂單需要哪些物料,庫存情況怎樣,哪些需要購買,哪些自已生產,在生產之前材料是否能準時到達工廠。企業內.sa...

Golang排程器GMP學習筆記(二)

我們通過 go func 來建立乙個goroutine 有兩個儲存g的佇列,乙個是區域性排程器p的本地佇列 乙個是全域性g佇列。新建立的g會先儲存在p的本地佇列中,如果p的本地佇列已經滿了就會儲存在全域性的佇列中 g只能執行在m中,乙個m必須持有乙個p,m與p是1 1的關係。m會從p的本地佇列彈出乙...

Golang排程器GMP學習筆記(一)

單程序時代的問題 多程序 多執行緒的問題 協程的問題m goroutine協程 n thread執行緒 m想要執行 放回g都必須訪問全域性g佇列,並且m有多個,即多執行緒訪問同一資源需要加鎖進行保證互斥 同步,所以全域性g佇列是有互斥鎖進行保護的。問題 建立 銷毀 排程g都需要每個m獲取鎖,這就形成...