processor的數量是在啟動時被設定為環境變數gomaxprocs的值,或者通過執行時排程函式gomaxprocs()進行設定。processor數量固定意味著任意時刻只有gomaxprocs個執行緒在執行著go**我們分別用三角形,矩形和圓形表示machine processor和goroutine。
正常情況下
所有的goroutine執行在同乙個m系統執行緒中,每乙個m系統執行緒維護乙個processor,任何時刻,乙個processor中只有乙個goroutine,其他goroutine在runqueue中等待。乙個goroutine執行完自己的時間片後,讓出上下文,回到runqueue中。 多核處理器的場景下,為了執行goroutines,每個m系統執行緒會持有乙個processor。
如果兩個m都在乙個cpu上執行,這就是併發;如果兩個m在不同的cpu上執行,這就是並行。在正常情況下,scheduler(排程器)會按照上面的流程進行排程,當乙個g(goroutine)的時間片結束後將p(processor)分配給下乙個g,但是執行緒會發生阻塞等情況,看一下goroutine對執行緒阻塞等的處理。
執行緒阻塞
當正在執行的goroutine(g0)阻塞的時候,例如進行系統呼叫,會再建立乙個系統執行緒(m1),當前的m0執行緒放棄了它的processor(p),p轉到新的執行緒中去執行。
runqueue執行完成
當其中乙個processor的runqueue為空,沒有goroutine可以排程,它會從另外乙個上下文偷取一半的goroutine。
首先建立乙個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暫存器進行現場恢復(從上次中斷位置繼續執行)。
golang GMP排程模型
多程序 多執行緒的問題 多執行緒 程序的壁壘 執行緒占用記憶體 約為4mb 高cpu排程消耗 1 1 n m 排程器的優化 早期go排程器 弊端 全域性佇列 p的本地佇列 p列表 m列表 p和m的數量 m數量問題 hand off 機制 利用並行 搶占 全域性g佇列 通過go func 建立乙個g ...
排程佇列模型
排程佇列模型及準則 1 僅有程序排程的排程佇列模型 每個程序在執行時都可能出現以下三種情況 1 任務在給定的時間片內已經完成,該程序便在釋放處理機後進入完成狀態 2 任務在本次分得的時間片內尚未完成,os便將該任務再放入就緒佇列的末尾 3 在執行期間,程序因為某事件而被阻塞後,被os放入阻塞佇列。2...
Goroutine的排程模型
當前有兩個p,各自繫結了乙個m,每個p上掛了乙個本地goroutine佇列,也有乙個全域性goroutine佇列。流程 每次使用go關鍵字宣告時,乙個g物件被建立並加入到本地g佇列或者全域性g佇列。檢查是否有空閒的p 處理器 若有那麼建立乙個m 若有正在sleep的m那麼直接喚醒它 與其繫結,然後這...