菜鳥系列Golang學習 協程

2022-07-25 21:57:18 字數 2581 閱讀 3282

有興趣的關注it程式設計師客棧哦

核心態:cpu可以訪問記憶體的所有資料,包括外圍裝置,例如硬碟,網絡卡,cpu也可以將自己從乙個程式切換到另乙個程式。

使用者態:只能受限的訪問記憶體,且不允許訪問外圍裝置,占用cpu的能力被剝奪,cpu資源可以被其他程式獲取。

由於需要限制不同的程式之間的訪問能力, 防止他們獲取別的程式的記憶體資料, 或者獲取外圍裝置的資料, 併發送到網路, cpu劃分出兩個許可權等級 -- 使用者態和核心態。

程序

程序是資源(cpu、記憶體等)分配的基本單位,它是程式執行時的乙個例項。程式執行時系統就會建立乙個程序,並為它分配資源,然後把該程序放入程序就緒佇列,程序排程器選中它的時候就會為它分配cpu時間,程式開始真正執行。

執行緒

執行緒是程式執行時的最小單位,它是程序的乙個執行流,是cpu排程和分派的基本單位,乙個程序可以由很多個執行緒組成,執行緒間共享程序的所有資源,每個執行緒有自己的堆疊和區域性變數。執行緒由cpu獨立排程執行,在多cpu環境下就允許多個執行緒同時執行。同樣多執行緒也可以實現併發操作,每個請求分配乙個執行緒來處理。

協程

協程是一種使用者態的輕量級執行緒,協程擁有自己的暫存器上下文和棧。協程排程切換時,將暫存器上下文和棧儲存到其他地方,在切回來的時候,恢復先前儲存的暫存器上下文和棧。因此,協程能保留上一次呼叫時的狀態(即所有區域性狀態的乙個特定組合),每次過程重入時,就相當於進入上一次呼叫的狀態,換種說法:進入上一次離開時所處邏輯流的位置。執行緒和程序的操作是由程式觸發系統介面,最後的執行者是系統;協程的操作執行者則是使用者自身程式,goroutine也是協程。

golang 從 2009 年正式發布以來,依靠其極高執行速度和高效的開發效率,迅速佔據市場份額。golang 從語言級別支援併發,通過輕量級協程 goroutine 來實現程式併發執行。

goroutine 非常輕量,主要體現在以下兩個方面:

上下文切換代價小: goroutine 上下文切換只涉及到三個暫存器(pc / sp / dx)的值修改;而對比執行緒的上下文切換則需要涉及模式切換(從使用者態切換到核心態)、以及 16 個暫存器、pc、sp…等暫存器的重新整理;

記憶體占用少:執行緒棧空間通常是 2m,goroutine 棧空間最小 2k;

golang 程式中可以輕鬆支援10w 級別的 goroutine 執行,而執行緒數量達到 1k 時,記憶體占用就已經達到 2g。

go 程式通過排程器來排程goroutine 在核心執行緒上執行,但是 goroutine 並不直接繫結 os 執行緒 m - machine執行,而是由 goroutine scheduler 中的 p - processor (邏輯處理器)來作獲取核心執行緒資源的『中介』。go 排程器模型我們通常叫做g-p-m 模型,他包括 4 個重要結構,分別是g、p、m、sched:

go的排程器內部有四個重要的結構:m,p,s,sched,如上圖所示(sched未給出)

從上圖中看,有2個物理執行緒m,每乙個m都擁有乙個處理器p,每乙個也都有乙個正在執行的goroutine。

p的數量可以通過gomaxprocs()來設定,它其實也就代表了真正的併發度,即有多少個goroutine可以同時執行。

圖中灰色的那些goroutine並沒有執行,而是出於ready的就緒態,正在等待被排程。p維護著這個佇列(稱之為runqueue),

go語言裡,啟動乙個goroutine很容易:go function 就行,所以每有乙個go語句被執行,runqueue佇列就在其末尾加入乙個

goroutine,在下乙個排程點,就從runqueue中取出(如何決定取哪個goroutine?)乙個goroutine執行。

當乙個os執行緒m0陷入阻塞時(如下圖),p轉而在執行m1,圖中的m1可能是正被建立,或者從執行緒快取中取出。

當mo返回時,它必須嘗試取得乙個p來執行goroutine,一般情況下,它會從其他的os執行緒那裡拿乙個p過來,

如果沒有拿到的話,它就把goroutine放在乙個global runqueue裡,然後自己睡眠(放入執行緒快取裡)。所有的p也會週期性的檢查global runqueue並執行其中的goroutine,否則global runqueue上的goroutine永遠無法執行。

另一種情況是p所分配的任務g很快就執行完了(分配不均),這就導致了這個處理器p很忙,但是其他的p還有任務,此時如果global runqueue沒有任務g了,那麼p不得不從其他的p裡拿一些g來執行。一般來說,如果p從其他的p那裡要拿任務的話,一般就拿run queue的一半,這就確保了每個os執行緒都能充分的使用,如下圖:

Golang學習篇 協程池

目錄 1.為什麼需要協程池?2.簡單的協程池 3.go playground pool 4.ants 推薦 雖然go語言自帶 高併發 的標籤,其併發程式設計就是由groutine實現的,因其消耗資源低 大約2kb左右,執行緒通常2m左右 效能高效,開發成本低的特性而被廣泛應用到各種場景,例如服務端開...

Golang協程排程

有時候可能會出現這種情況,乙個無恥的goroutine阻止其他goroutine執行。當你有乙個不讓排程器執行的 for迴圈時,這就會發生。package main import fmt func main for done fmt.println done for迴圈並不需要是空的。只要它包含了不...

golang 協程理解

本文總結一下go協程的理解,如有錯誤望請指正。網上都說協程是一種輕量級執行緒,執行緒又是一種輕量級的程序。這話在語言層面看來是沒有錯的,但它們的實現是不同的。執行緒是cpu資源排程的最小單位。協程不由cpu進行排程,由應用程式進行排程,也就是由go進行排程。在go中,協程的排程也有專門的排程器。但g...