golang的排程總結

2021-10-02 19:06:31 字數 1407 閱讀 9197

golang語言特性就是以併發著稱,golang的併發好跟它的排程系統不無關係。本文主要總結一下個人對golang排程的理解。

主要從幾個方面進行總結(針對現如今流行的多核cpu架構):

作業系統的執行緒排程

golang會在什麼時候進行排程決策

golang是如何進行排程的

比如乙個具有8個執行緒的程式在一台4核八執行緒的計算機上執行,這個理論上8個執行緒是可以同時被執行的,但是這個程式超過了8個執行緒的話,那麼其餘的執行緒就必須需要等待作業系統的排程了,等待其他執行緒讓出cpu的時間片,才有機會執行。

以下幾點將會導致golang排程系統的進行排程決策:

使用go關鍵字

golang進行gc的時候

進行系統呼叫的時候

同步處理的時候

golang的排程模型是pmg模型

假如我的計算機是4核八執行緒,任何乙個go程式會有八個 虛擬核心可以利用,也就是有八個p,每個p都會分配乙個m,m是作業系統級別的執行緒,這就意味著任何乙個golang程式就有8個可用的執行緒去處理。

每個go程式都會有乙個初始的goroutine(也就g),goroutine也稱為使用者態執行緒。

還有乙個重要的是,golang的排程中有兩個重要的概念:本地執行佇列與全域性執行佇列。每個p都會繫結乙個本地執行佇列。

下重點介紹一下,go程式在進行系統呼叫時是如何排程的,進行系統呼叫又分為非同步系統呼叫與同步系統呼叫。

非同步系統呼叫

當您執行的作業系統能夠非同步處理系統呼叫時,golang的排程器可以防止goroutine在進行系統呼叫的時候阻塞m,這個時候m可以去執行繫結的p的goroutine本地執行佇列的其他goroutine,而不用讓當前的p解綁後與新建乙個m,或者別的空閒的m繫結後再執行goroutine本地執行佇列。一但系統呼叫完成之後,該goroutine會再次進入本地執行佇列進行排隊,等待執行

同步系統呼叫

但是當乙個goroutine-1進行系統呼叫卻又不能非同步進行時怎麼辦呢?這個時候goroutine-1會導致當前m-1阻塞,排程器會將p-1與m-1解綁,將p-1重新掛到空閒的m-2,或者其他m上,繼續執行p-1繫結的本地執行佇列的其他g,值得注意的是,此時g-1還在m-1上等待呼叫返回,呼叫完成之後,重新回到本地佇列進行排隊,等待執行。

還有乙個排程場景,就是golang排程的搶占式排程。比如有兩個m, m1與m2分別對應著p1、p2(預設情況下是使用乙個cpu核的,p的數量可以通過gomaxprocs()來設定),對應相應的兩個本地執行佇列。假如m1已經處理完它相應的g,而臨近的m2還沒有完成處理,則p1就會去p2繫結的本地執行佇列中強一般的g來執行,m1與m2都處理完了,p1與p2就會去全域性執行佇列中取g,再去進行執行。

以上就是golang的排程總結,比較粗糙,但是也算能供自己去覆盤理解

【參考文章】

william kennedy關於golang排程的系列部落格 –

golang排程過程

1.執行時系統相關模組 這一節只講述排程系統。2.與排程相關的有下列資料有 1 全域性表就不用多解釋,排程器不是乙個專門的執行緒,而是一種資源,每個m都可能會對其進行查詢,如 m的呼叫的時候,會首先查詢排程器中的可執行佇列g,然後查詢本地p執行佇列 在m不夠的時候,會首先排程器空閒的m列表中查詢 在...

Golang協程排程

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

golang 排程學習 綜述

本文將會描述golang排程的大致方式,並介紹後文中將會用到的一些資料結構,及實現原理 注 這本是給自己學習用的筆記,其中包含一些網上大牛的資料節選片段,也忘了出處,求海涵。大佬不願意可以聯絡刪除謝謝。主要參考 go語言學習筆記 一般多執行緒會有以下幾種執行緒模型 go採用方案 採用兩級 混合型 執...