g(goroutine) :我們所說的協程,為使用者級的輕量級執行緒,每個goroutine物件中的sched儲存著其上下文資訊.
// go1.11版本預設stack大小為2kb
_stackmin = 2048
// 建立乙個g物件,然後放到g佇列
// 等待被執行
func newproc1(fn *funcval, argp *uint8, narg int32, callergp *g, callerpc uintptr)
// 以下省略}
m(machine) :對核心級執行緒的封裝,數量對應真實的cpu數(真正幹活的物件).
type m struct
p(processor) :即為g和m的排程物件,用來排程g和m之間的關聯關係,其數量可通過gomaxprocs()來設定,預設為核心數.
首先建立乙個g物件,g物件儲存到p本地佇列或者是全域性佇列。p此時去喚醒乙個m。p繼續執行它的執行序。m尋找是否有空閒的p,如果有則將該g物件移動到它本身。接下來m執行乙個排程迴圈(呼叫g物件->執行->清理執行緒→繼續找新的goroutine執行)。
m執行過程中,隨時會發生上下文切換。當發生上線文切換時,需要對執行現場進行保護,以便下次被排程執行時進行現場恢復。go排程器m的棧儲存在g物件上,只需要將m所需要的暫存器(sp、pc等)儲存到g物件上就可以實現現場保護。當這些暫存器資料被保護起來,就隨時可以做上下文切換了,在中斷之前把現場儲存起來。如果此時g任務還沒有執行完,m可以將任務重新丟到p的任務佇列,等待下一次被排程執行。當再次被排程執行時,m通過訪問g的vdsosp、vdsopc暫存器進行現場恢復(從上次中斷位置繼續執行)。
相比大多數並行設計模型,go比較優勢的設計就是p上下文這個概念的出現,如果只有g和m的對應關係,那麼當g阻塞在io上的時候,m是沒有實際在工作的,這樣造成了資源的浪費,沒有了p,那麼所有g的列表都放在全域性,這樣導致臨界區太大,對多核排程造成極大影響。
而goroutine在使用上面的特點,感覺既可以用來做密集的多核計算,又可以做高併發的io應用,做io應用的時候,寫起來感覺和對程式設計師最友好的同步阻塞一樣,而實際上由於runtime的排程,底層是以同步非阻塞的方式在執行(即io多路復用)。
所以說保護現場的搶占式排程和g被阻塞後傳遞給其他m呼叫的核心思想,使得goroutine的產生。
深入理解Golang排程器GMP模型
隨著伺服器硬體的公升級,配置越來越高,為了充分利用伺服器資源,併發變成也就變得越來越重要。併發 邏輯上具有處理多個同時任務的能力。並行 物理上同一時刻執行多個併發任務。通常所說的併發程式設計,也就是說它允許多個任務同時執行,但實際上並不一定在同一時刻被執行。在單核處理器上,通過多執行緒共享cpu時間...
golang排程器原理與GMP模型設計思想
n 1 1.法利 多個cpu 2.出現阻塞的瓶頸 1 1 1.跟多執行緒 多程序模型 異 2.切換協程成本代價昂貴 m n 1.能夠利 多核 2.過於依賴協程排程器的優化和算 法 記憶體佔 kb 量開闢 靈活排程 切換成本低 早期的go的排程器 基本的全域性go佇列和 較傳統的 輪詢利 多個thre...
Golang排程器GMP學習筆記(二)
我們通過 go func 來建立乙個goroutine 有兩個儲存g的佇列,乙個是區域性排程器p的本地佇列 乙個是全域性g佇列。新建立的g會先儲存在p的本地佇列中,如果p的本地佇列已經滿了就會儲存在全域性的佇列中 g只能執行在m中,乙個m必須持有乙個p,m與p是1 1的關係。m會從p的本地佇列彈出乙...