Golang協程調度原理( G、M、P)


1. 什么是協程?

協程,又稱微線程,纖程。英文名Coroutine。對於進程、線程,都是有內核進行調度,有CPU時間片的概念,進行搶占式調度。協程的調用有點類似子程序,但是和子程序相比,協程有掛起的概念,協程可以掛起跳轉執行其他協程,合適的時機再跳轉回來。

goroutine使用方式非常的簡單,只需使用go關鍵字即可啟動一個協程,並且它是處於異步方式運行,你不需要等它運行完成以后在執行以后的代碼。

2. 協程調度原理?



G(Goroutine):一個G代表一個goroutine

M(Machine):內核級線程,一個M代表了一個內核線程,等同於系統線程

P(Process):處理器,用來管理和執行goroutine,一個P代表了M所需的上下文環境

Sched:代表調度器,它維護有存儲M和G的隊列以及調度器的一些狀態信息等。

G-M-P三者的關系與特點:

P的個數取決於設置的GOMAXPROCS,go新版本默認使用最大內核數,比如你有8核處理器,那么P的數量就是8

M的數量和P不一定匹配,可以設置很多M,M和P綁定后才可運行,多余的M處於休眠狀態。

P包含一個LRQ(Local Run Queue)本地運行隊列,這里面保存着P需要執行的協程G的隊列,除了每個P自身保存的G的隊列外,調度器還擁有一個全局的G隊列GRQ(Global Run Queue),這個隊列存儲的是所有未分配的協程G。

三者關系:G需要綁定在M上才能運行,M需要綁定P才能運行。

簡單的來說,一個G的執行需要M和P的支持,一個M在與一個P關聯之后形成了一個有效的G運行環境【內核線程 + 上下文環境】,每個P都會包含一個可運行的G的隊列。

3. 調度實現?



從上圖中看,有2個物理線程M,每一個M都擁有一個處理器P,每一個也都有一個正在運行的goroutine。P的數量可以通過GOMAXPROCS()來設置,它其實也就代表了真正的並發度,即有多少個goroutine可以同時運行。圖中灰色的那些goroutine並沒有運行,而是出於ready的就緒態,正在等待被調度。P維護着這個隊列(稱之為runqueue),Go語言里,啟動一個goroutine很容易:go function 就行,所以每有一個go語句被執行,runqueue隊列就在其末尾加入一個goroutine,在下一個調度點,就從runqueue中取出(如何決定取哪個goroutine?)一個goroutine執行。
 

線程分為內核態線程和用戶態線程,用戶態線程需要綁定內核態線程,CPU並不能感知用戶態線程的存在,它只知道它在運行1個線程,這個線程實際是內核態線程。

用戶態線程實際有個名字叫協程(co-routine),為了容易區分,我們使用協程指用戶態線程,使用線程指內核態線程。

協程跟線程是有區別的,線程由CPU調度是搶占式的,協程由用戶態調度是協作式的,一個協程讓出CPU后,才執行下一個協程。

調度器的有兩大思想:

復用線程:協程本身就是運行在一組線程之上,不需要頻繁的創建、銷毀線程,而是對線程的復用。在調度器中復用線程還有2個體現:1)work stealing,當本線程無可運行的G時,嘗試從其他線程綁定的P偷取G,而不是銷毀線程。2)hand off,當本線程因為G進行系統調用阻塞時,線程釋放綁定的P,把P轉移給其他空閑的線程執行。

利用並行:GOMAXPROCS設置P的數量,當GOMAXPROCS大於1時,就最多有GOMAXPROCS個線程處於運行狀態,這些線程可能分布在多個CPU核上同時運行,使得並發利用並行。另外,GOMAXPROCS也限制了並發的程度,比如GOMAXPROCS = 核數/2,則最多利用了一半的CPU核進行並行。

調度器的兩小策略:

搶占:在coroutine中要等待一個協程主動讓出CPU才執行下一個協程,在Go中,一個goroutine最多占用CPU 10ms,防止其他goroutine被餓死,這就是goroutine不同於coroutine的一個地方。全局G隊列:在新的調度器中依然有全局G隊列,但功能已經被弱化了,當M執行work stealing從其他P偷不到G時,它可以從全局G隊列獲取G。

全局G隊列:在新的調度器中依然有全局G隊列,但功能已經被弱化了,當M執行work stealing從其他P偷不到G時,它可以從全局G隊列獲取G。

原文鏈接:https://blog.csdn.net/finghting321/article/details/107226778


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM