圖解 g0:特殊的 goroutine

ℹ️ 這篇文章基於 Go 1.13。

在 Go 中創建的所有 Goroutine 都會被一個內部的調度器所管理。Go 調度器嘗試爲所有的 Goroutine 分配運行時間,並且在當前的 Goroutine 阻塞或者終止的時候,Go 調度器會通過運行 Goroutine 的方式使所有 CPU 保持忙碌狀態。這個調度器實際上是作爲一個特殊的 Goroutine 運行的。

調度 goroutine

Go 使用 GOMAXPROCS 變量限制同時運行的 OS 線程數量,這意味着 Go 必須對每個運行着的線程上的 Goroutine 進行調度和管理。這個調度的功能被委託給了一個叫做 g0 的特殊的 goroutine, g0 是爲每個 OS 線程創建的第一個 goroutine:

之後,g0 會把就緒狀態的 Goroutine 調度到線程上去運行。

我建議你閱讀我的文章 “ Go:Goroutine,OS 線程和 CPU 管理 [1]”,來了解更多關於 PMG 模型的信息。

爲了更好的理解 g0 的調度策略,來回顧下 channel 的用法。下面是一個 Goroutine 在向 channel 發送數據是阻塞的例子:

ch := make(chan int)
[...]
ch <- v

當在 channel 上阻塞時,當前的 Goroutine 會被停放( parked ),即處於等待狀態( waiting mode ),並且不會被放在任何 Goroutine 隊列中:

之後,g0 會替換 Goroutine 並進行一輪調度:

本地隊列在調度過程中具有優先級,2 號 Goroutine 會被運行:

我建議你閱讀我的文章 “ Go: Go 調度器中的工作竊取(Work-Stealing)[2]” 來了解更多關於調度優先級的細節。

一旦有接收者讀取 channel 中的數據,7 號 Goroutine 就會解除阻塞狀態:

v := <-ch

收到消息的 Goroutine 會切換到 g0,並且通過放入本地隊列的方式將該 Goroutine 從停放狀態解鎖:

雖然這個特殊的 Goroutine 管理調度策略,但這並不是它唯一的工作,它還負責着更多的工作。

職責

與普通 Goroutine 不同的是,g0 有着固定且更大的棧,這使得在需要更大的棧的時候,以及棧不宜增長的時候,Go 可以進行操作。在 g0 的職責中,我們可以列出:

新創建的 Goroutine 優先運行,並且被放在本地隊列的頂部。

建議閱讀我的文章 “Go:併發與調度器親和性( Go: Concurrency & Scheduler Affinity )[3]” 瞭解更多關於 Goroutine 優先級的信息。

這個特殊的 Goroutine 涉及許多其他操作(較大空間的對象分配,cgo 等),需要較大的棧來保證我們的程序進行更高效的管理操作,以保持程序的低內存打印效率。


via: https://medium.com/a-journey-with-go/go-g0-special-goroutine-8c778c6704d8

作者:Vincent Blanchon[4] 譯者:dust347[5] 校對:polaris1119[6]

本文由 GCTT[7] 原創編譯,Go 中文網 [8] 榮譽推出

參考資料

[1]

Go:Goroutine,OS 線程和 CPU 管理: https://medium.com/a-journey-with-go/go-goroutine-os-thread-and-cpu-management-2f5a5eaf518a

[2]

Go: Go 調度器中的工作竊取(Work-Stealing): https://medium.com/a-journey-with-go/go-work-stealing-in-go-scheduler-d439231be64d

[3]

Go:併發與調度器親和性( Go: Concurrency & Scheduler Affinity ): https://medium.com/a-journey-with-go/go-concurrency-scheduler-affinity-3b678f490488

[4]

Vincent Blanchon: https://medium.com/@blanchon.vincent

[5]

dust347: https://github.com/dust347

[6]

polaris1119: https://github.com/polaris1119

[7]

GCTT: https://github.com/studygolang/GCTT

[8]

Go 中文網: https://studygolang.com/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/_Tl1cGTdPxwSF1ctHc1yZg