Golang GMP原理(1) 概念梳理 線程 線程一般指內核級線程,核心如下: 操作系統的最小調度單元 創建 銷毀 調度由內核完成,cpu要完成內核態與用戶態的轉換 可充分利用多核,實現並行 協程 協程線程對應 協程,又稱為用戶級線程,核心點如下: 與線程存在映射關係,為M:1 創建、銷毀、調度在 ...
Golang GMP原理(1)
概念梳理
線程
線程一般指內核級線程,核心如下:
- 操作系統的最小調度單元
- 創建 銷毀 調度由內核完成,cpu要完成內核態與用戶態的轉換
- 可充分利用多核,實現並行
協程
協程線程對應
協程,又稱為用戶級線程,核心點如下:
- 與線程存在映射關係,為M:1
- 創建、銷毀、調度在用戶態完成,對內核透明,所以更輕
- 從屬同一個內核級線程,無法並行;一個協程阻塞會導致從屬同一線程的所有協程無法執行。
Goroutine
Goroutine是特殊的協程
- 與線程存在映射關係,為M:N
- 創建、銷毀、調度在用戶態完成,對內核透明,足夠輕便
- 可利用多個線程實現並行
- 通過調度器實現和線程間的動態綁定和調度
- 棧空間可動態擴縮。
對比
模型 | 弱依賴內核 | 可並行 | 可應對阻塞 | 棧可動態擴縮 |
---|---|---|---|---|
線程 | × | √ | √ | × |
協程 | √ | × | × | × |
goroutine | √ | √ | √ | √ |
GMP模型
g
- g是goroutine,是對協程的抽象
- g有自己的運行棧、狀態、以及執行的任務函數(用戶通過go func指定)
- g需要綁定到p才能執行,在g的視角中,p是它的cpu
p
- p是調度器,聯繫g與m
- p的數量決定了g最大並行數量,可由用戶通過GOMAXPROCS進行設定(超過CPU核數無意義)
m
- m是machine 是go中線程的抽象
- m不直接執行g,而是先和p綁定,由其實現代理
- 藉由p的存在,m無需和g綁死,也無需記錄g的狀態信息,因此g在全生命周期中可實現跨m執行
gmp
- m是線程的抽象 g是goroutine p'是調度器
- m調度g前 需要和p綁定
- 全局有多個m和p 同時並行的g最大數量等於p的數量
- g的存放隊列有三類:P的本地隊列;全局隊列;和wait隊列(圖中未展示,為io阻塞就緒態goroutine隊列)
- m調度g時,優先取p本地隊列,其次取全局隊列,最後取wait隊列;這樣的好處是,取本地隊列時,可以接近於無鎖化,減少全局鎖競爭;
- 為防止不同p的閑忙差異過大,設立work-stealing機制,本地隊列為空的p可以嘗試從其他p本地隊列偷取一半的g補充到自身隊列.