意犹未尽 —— GPM 的状态流转(十)
最開始的時候,我們講了 GPM 到底是什么,當時沒有看過太多源碼,所以對 GPM 沒有一個整體上的認識。
現在我們終于到了快要結束的時候,可以從宏觀上總結一下 GPM,這篇文章嘗試從它們的狀態流轉角度總結。
首先是 G 的狀態流轉:
圖上除了 park_m 和 ready 這一塊外其他都有涉及。這一對函數在前面講 channel 的時候有提到,后面我們有機會再單獨說一下這部分。
上圖省略了一些垃圾回收的狀態,畢竟這個系列沒有講這一塊。完整的狀態流轉圖可以到參考資料【歐神 調度器初始化】里看。
接著是 P 的狀態流轉:
通常情況下(在程序運行時不調整 P 的個數),P 只會在上圖中的四種狀態下進行切換。當程序剛開始運行進行初始化時,所有的 P 都處于 _Pgcstop 狀態, 隨著 P 的初始化( runtime.procresize),會被置于 _Pidle。
當 M 需要運行時,會 runtime.acquirep 來使 P 變成 Prunning 狀態,并通過 runtime.releasep 來釋放。
當 G 執行時需要進入系統調用,P 會被設置為 _Psyscall, 如果這個時候被系統監控搶奪( runtime.retake),則 P 會被重新修改為 _Pidle。
如果在程序運行中發生 GC,則 P 會被設置為 _Pgcstop, 并在 runtime.startTheWorld 時重新調整為 _Prunning。
上面這段引用自【歐神 調度器初始化】。
最后,我們來看 M 的狀態變化:
M 只有自旋和非自旋兩種狀態。自旋的時候,會努力找工作;找不到的時候會進入非自旋狀態,之后會休眠,直到有工作需要處理時,被其他工作線程喚醒,又進入自旋狀態。
這是調度器系列的最后一篇文章了。整個系列的核心在于:
GPM 的初始化;
M 是怎樣一步步找工作;
用戶棧和 g0 棧的切換;
schedule 的調度循環是怎樣運轉的;
監控線程做了什么。
其他和 GC 相關的,我們暫時并未涉及到,留到后續再探索。
調度器的探索我們就要告一段落了,感謝陪伴。
參考資料
【歐神 調度器初始化】https://github.com/changkun/go-under-the-hood/blob/master/book/zh-cn/part2runtime/ch06sched/init.md【Go 夜讀 boya】https://reading.developerlearning.cn/reading/12-2018-08-02-goroutine-gpm/超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生
總結
以上是生活随笔為你收集整理的意犹未尽 —— GPM 的状态流转(十)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 千难万险 —— goroutine 从生
- 下一篇: 忠于职守 —— sysmon 线程到底做