Go語言學習 goroutine

2021-09-25 05:55:37 字數 2413 閱讀 2699

簡介

goroutine是go語言中最為nb的設計,也是其魅力所在,goroutine的本質是協程,是實現平行計算的核心。goroutine使用方式非常的簡單,只需使用go關鍵字即可啟動乙個協程,並且它是處於非同步方式執行,你不需要等它執行完成以後在執行以後的**。

go func()//通過go關鍵字啟動乙個協程來執行函式

內部原理

在講解原理之前,我們先了解下一些關鍵性術語的概念

乙個cpu上能同時執行多項任務,在很短時間內,cpu來回切換任務執行(在某段很短時間內執行程式a,然後又迅速得切換到程式b去執行),有時間上的重疊(巨集觀上是同時的,微觀仍是順序執行),這樣看起來多個任務像是同時執行,這就是併發。

當系統有多個cpu時,每個cpu同一時刻都執行任務,互不搶占自己所在的cpu資源,同時進行,稱為並行。

cpu在切換程式的時候,如果不儲存上乙個程式的狀態(也就是我們常說的context–上下文),直接切換下乙個程式,就會丟失上乙個程式的一系列狀態,於是引入了程序這個概念,用以劃分好程式執行時所需要的資源。因此程序就是乙個程式執行時候的所需要的基本資源單位(也可以說是程式執行的乙個實體)。

cpu切換多個程序的時候,會花費不少的時間,因為切換程序需要切換到核心態,而每次排程需要核心態都需要讀取使用者態的資料,程序一旦多起來,cpu排程會消耗一大堆資源,因此引入了執行緒的概念,執行緒本身幾乎不占有資源,他們共享程序裡的資源,核心排程起來不會那麼像程序切換那麼耗費資源。

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

groutine能擁有強大的併發實現是通過gpm排程模型實現,下面就來解釋下goroutine的排程模型。

golang的goroutine排程和多對多模型密切相關,golang自己有自己的排程器scheduler,它維護著儲存m和g的佇列以及排程器的一些狀態資訊等。golang的排程器內部有三個重要結構:m、p和g。

- m:m代表核心級執行緒,乙個m就是乙個執行緒,goroutine就是跑在m之上的;m是乙個很大的結構,裡面維護小物件記憶體cache(mcache)、當前執行的goroutine、隨機數發生器等等非常多的資訊

- g:代表乙個goroutine,它有自己的棧,instruction pointer和其他資訊(正在等待的channel等等),用於排程。

- p:p全稱是processor,處理器,它的主要用途就是用來執行goroutine的,所以它也維護了乙個goroutine佇列,裡面儲存了所有需要它來執行的goroutine

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

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

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

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

goroutine,在下乙個排程點,就從runqueue中取出乙個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執行緒都能充分的使用,如下圖:

使用goroutine

Go語言學習之goroutine詳解

什麼是goroutine?goroutine是建立 程之上的輕量級的抽象。它允許我們以非常低的代價在同乙個位址空間中並行地執行多個函式或者方法。相比於執行緒,它的建立和銷毀的代價要小很多,並且它的排程是獨立於執行緒的。在golang中建立乙個goroutine非常簡單,使用 go 關鍵字即可 pac...

GO語言學習

sudo apt get install golang但是用ubuntu的庫安裝有幾個不好的地方 因此建議不要使用ubuntu的庫安裝golang環境 golang社群的安裝指導 wget tar c usr local zxf go1.6.2.linux amd64.tar.gz設定環境變數,修改...

Go語言學習

執行 go run go main函式 打包 go build 用於測試編譯包,在專案目錄下生成可執行檔案 有main包 go install 主要用來生成庫和工具。一是編譯包檔案 無main包 將編譯後的包檔案放到 pkg 目錄下 gopath pkg 二是編譯生成可執行檔案 有main包 將可執...