下面看看golang的協程調度golang
groutine能擁有強大的併發實現是經過GPM調度模型實現,下面就來解釋下goroutine的調度模型。緩存
Golang採用的是多線程模型,更詳細的說他是一個兩級線程模型,但它對系統線程(內核級線程)進行了封裝,暴露了一個輕量級的協程goroutine(用戶級線程)供用戶使用,而用戶級線程到內核級線程的調度由golang的runtime負責,調度邏輯對外透明。goroutine的優點在於上下文切換在徹底用戶態進行,無需像線程同樣頻繁在用戶態與內核態之間切換,節約了資源消耗。多線程
當一個OS線程M0陷入阻塞時(以下圖),P轉而在運行M1,圖中的M1多是正被建立,或者從線程緩存中取出。併發
一、P的數量:函數
二、M的數量:線程
M與P的數量沒有絕對關係,一個M阻塞,P就會去建立或者切換另外一個M,因此,即便P的默認數量是1,也有可能會建立不少個M出來。debug
三、P什麼時候建立:在肯定了P的最大數量n後,運行時系統會根據這個數量建立n個P。3d
四、M什麼時候建立:沒有足夠的M來關聯P並運行其中的可運行的G。好比全部的M此時都阻塞住了,而P中還有不少就緒任務,就會去尋找空閒的M,而沒有空閒的,就會去建立新的M。協程
當M因系統調用而阻塞時(M上運行的G進入了系統調用的時候),M與P會分開,若是此時P的就緒隊列中還有任務,
P就會去關聯一個空閒的M,或者建立一個M進行關聯。(也就是說go不是像libtask同樣處理IO阻塞的?不肯定。)對象
若是一個P的就緒隊列全部任務都執行完了,那麼P會嘗試從其餘P的就緒隊列中取出一部分到本身的就緒隊列中,以保證每一個P的就緒隊列都有任務能夠執行。