Go語言的協程,系統執行緒以及CPU管理

2021-10-01 14:56:09 字數 3569 閱讀 8107

建立系統執行緒以及在系統執行緒間切換,會對程式的記憶體和效能造成較大的開銷。

go 的目標是盡量利用 cpu 多核資源。設計之初就考慮了高併發性。

為了達到這個目標,go擁有乙個將協程排程到系統執行緒執行的排程器

這個排程器定義了三個核心概念,在go原始碼中是這樣解釋的:

m必須有乙個相關聯的p才能執行go**。

以下是p,m,g模型的示意圖:

每個協程(g)在乙個分配給邏輯處理器(p)的系統執行緒(m)上執行。

首先,go會根據當前機器的邏輯cpu個數來建立相應數量的p,並將它們存放在一張空閒p列表中

然後,新建立並等待被執行的 goroutine 協程會喚醒乙個p來執行這個任務,這個p會建立乙個和系統核心級執行緒相關聯的使用者級執行緒m

p一樣,如果乙個m沒有工作可做了,該m會被放入空閒m鍊錶中

在程式啟動時,go會預先建立一些核心級執行緒以及相關聯的使用者級執行緒m

在上面的小例子中,第乙個列印hello的協程會使用主協程,而第二個列印world的協程會從空閒列表中獲取到乙個m和乙個p

以上,我們有了一張管理協程核心執行緒的全域性圖,讓我們進一步看看go在什麼情況下會使用更多的mp,以及系統呼叫時協程是如何被管理的。

go對系統呼叫做了優化,具體做法是在執行時對系統呼叫做了封裝(不管系統呼叫是否會造成阻塞)。

該部分封裝**會自動將上下文環境p與使用者執行緒m解除繫結,使得另乙個使用者執行緒m可以在這個p上執行。

讓我們來看乙個讀取檔案的例子:

func

main()

以下是開啟檔案的流程:

g執行系統呼叫,p0被放入空閒列表中,可被使用。

當系統呼叫結束之後,go順序執行如下流程直到其中一條規則被滿足:

試圖獲取同乙個p,在我們上面的例子就是p0,如果獲取到,則恢復執行。

試圖在空閒列表中獲取乙個p,如果獲取到,則恢復執行。

g(協程)放入全域性佇列中,將相關的m放入空閒列表中。

go使用非阻塞i/o模式,對資源還沒有就緒的情況也做了處理,比如說http請求。

這種情況下首先也遵循上面所說的系統呼叫的流程,之後如果底層的系統呼叫由於資源沒有就緒而返回失敗時,go會強制使用network poller,並且將該協程掛起。

以下是例子:

當使用了系統呼叫時,go並不限制這些可能被阻塞的系統執行緒的數量,以下是go**中的注釋說明:

gomaxprocs變數限制的是使用者層面go**的系統執行緒數量。

對於可能造成阻塞的系統呼叫的執行緒數是不做限制的;它們不計算在gomaxprocs限制之中。

以下是乙個例子

func

main()

()} wg.

wait()

}

值得一提,由於go可以復用核心執行緒,所以工具檢視到的執行緒數要小於例子中for迴圈的次數。

以下是使用tracing工具,檢視程式建立的執行緒數量:

100個協程被對映到了2個執行緒上

go語言之goroute協程

goroute協程 程序和執行緒 程序是系統進行資源分配和排程的基本單位,執行緒是cpu排程和發派的基本單位,乙個程序可以建立和撤銷多個執行緒 併發和並行 多執行緒程式在乙個核的cpu上面執行,是併發 多執行緒程式在多個核的cpu上面執行,這是並行 協程和執行緒 協程 獨立的棧空間,共享的堆記憶體,...

執行緒程序以及協程的區別

程序,儲存在硬碟上的程式執行之後,會在記憶體裡形成乙個獨立的記憶體體,這個記憶體體有自己獨立的位址空間,有自己的堆,上級掛靠單位是作業系統,作業系統會以程序為單位分配系統資源 cpu時間片,記憶體等資源 程序是資源分配的最小單位。執行緒也成為輕量級執行緒,是作業系統排程 cpu排程 執行的最小單位 ...

Go語言學習筆記 Go協程

併發 concurrency 是指一次處理大量事情的能力。讓我們用乙個 例子來說明。並行 parallelism 指的是同時處理多個事情。雖然聽起來像併發,但是它們是不同的。go 原生支援併發。在go中,使用 go 協程 goroutine 和通道 channel 來處理併發。函式 main 就以 ...