Golang的協程調度器采用了一種稱為M:N調度的策略。這意味著它將M個用戶級線程(也稱為goroutines)調度到N個內核級線程(也稱為操作系統線程)上執行。
調度器的實現原理如下:
- 調度器會在啟動時創建一組操作系統線程,稱為M。這些線程負責執行goroutines。
- 當一個goroutine需要執行時,調度器會將其放入一個全局隊列中。
- 調度器會選擇一個空閑的M來執行隊列中的goroutine。如果沒有空閑的M,調度器會創建一個新的M。
- 當M開始執行goroutine時,它會接管該goroutine的執行權,直到它發生以下情況之一:
- 該goroutine主動放棄執行權,例如通過調用
time.Sleep()
或runtime.Gosched()
等函數。
- 該goroutine發生阻塞,例如等待I/O操作完成或等待通道的數據。
- 該goroutine執行完畢,即達到了函數的結束點。
- 該goroutine執行時間過長,超過了一定的閾值,調度器會將其搶占并重新調度。
- 當一個goroutine發生阻塞時,M會從當前線程中分離出來,使得該線程變為空閑狀態,可以被其他goroutines使用。
- 當一個阻塞的goroutine變為可執行狀態時,調度器會將其重新放入全局隊列中,并選擇一個空閑的M來執行它。
- 當一個M執行完一定數量的goroutines時,它會檢查全局隊列中是否還有未執行的goroutines。如果有,則繼續執行,否則,M會進入休眠狀態,等待新的goroutines到來。
- 當一個M處于休眠狀態時,調度器會定期喚醒它,以確保所有的M都能夠執行。
調度器會根據一些策略來決定如何選擇M和goroutines,例如負載均衡、搶占式調度等。這種M:N調度的模式可以充分利用多核處理器的資源,并提供高效的并發執行。