亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言中goroutine的調度原理是什么

發布時間:2021-07-06 16:31:41 來源:億速云 閱讀:162 作者:Leah 欄目:數據庫

Go語言中goroutine的調度原理是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

一、關于并發的基礎知識

在講goroutine的調度原理之前,有些與操作系統相關的知識,我們需要先知道,例如:

1.什么是并發?

并發:兩個或兩個以上的任務在一段時間內被執行。我們并不關心這些任務是否在同一時刻執行,我們只是知道,這些任務在這一段時間能能夠都被執行,當然這一段時間可以很長,也可以很短。

2.并發的最小并發單位是什么?

進程是計算機資源分配最小的單位,是CPU分配資源的基本單位,具有獨立的內存。

線程是計算機調度最小的單位,也是程序執行的最小單位,是在進程中的,一個進程往往會有一個到多個線程。

3.計算機是如何實現并發的?

計算機的分時調用是并發的根本,CPU通過快速的切換作業來執行不同的作業,基本的調度單位在執行的時候可以被阻塞掉,此時就會將CPU資源讓出來,等到該調度單位再次被喚醒的時候,又可以使用CPU資源,而操作系統保證了整個的調度過程。

二、Goroutine的基礎知識

除此之外,關于goroutine的調度原理,我們需要弄清楚下面幾個問題。

1.goroutine是什么?

Goroutine:是Go里的一種輕量級線程——協程。

1)相對線程,協程的優勢就在于它非常輕量級,進行上下文切換的代價非常的小。

2)對于一個goroutine ,每個結構體G中有一個sched的屬性就是用來保存它上下文的。這樣,goroutine 就可以很輕易的來回切換。

3)由于其上下文切換在用戶態下發生,根本不必進入內核態,所以速度很快。而且只有當前goroutine 的 PC, SP等少量信息需要保存。

4)在Go語言中,每一個并發的執行單元為一個goroutine。

Go 語言中的goroutine并發, 采用的是CSP(communicating sequential processes)并發模型,講究的是以通訊的方式來進行數據共享,是通過goroutine配合channel的方式來實現的。(備注:這部分知識后續單獨整理一章。)

2.既然它是比線程還小的粒度,那么它與線程有什么關系?

Go語言的線程模型就是一種特殊的兩級線程模型,如下所示:

兩級線程模型的實現非常復雜,和內核級線程模型類似,一個進程中可以對應多個內核級線程,但是進程中的線程不和內核線程一一對應;這種線程模型會先創建多個內核級線程,然后用自身的用戶級線程去對應創建的多個內核級線程,自身的用戶級線程需要本身程序去調度,內核級的線程交給操作系統內核去調度。

三、Goroutine的調度策略

我們先來看下,Go線程實現了MPG模型:

S(Sched):結構就是調度器,它維護有存儲M和G的隊列以及調度器的一些狀態信息等。

M(Machine):一個M直接關聯了一個內核線程。

P(processor):代表了M所需的上下文環境,也是處理用戶級代碼邏輯的處理器。G(Goroutine):其實本質上也是一種輕量級的線程。

它們的關系如下所示:

介紹:

一個M會關聯兩個東西,一個是內核線程,一個是可執行的進程。

一個上下文P會有兩類Goroutine,一類是正在運行的,圖中的藍色G;一類是正在排隊的,圖中灰色G,這個會存儲在該進程中的runqueue里面。

這里的上下文P的數量也表示的是Goroutinue運行的數量,一般設置為幾個,機器中就會并發運行幾個。當然這里P的數量是可以設置的,通過環境變量GOMAXPROCS的值,或者通過運行時調用函數runtime.GOMAXPROCS()進行設置,最大值是256。

有了上面的知識,我們知道了Goroutine的一些基本概念,但是我們還是不知道,Go的并發是如何調度的。而這一個話題,就需要我們將Goroutine的幾種場景(創建、銷毀和運行)做拆分。

1.在執行go語句之前,我們看下程序都做了哪些準備,也就是程序的初始化啟動流程是什么樣子的?

上面的代碼,有三個點非常關鍵,分別是runtime.schedinit,runtime.main,runtime.mstart

Step1: runtime.schedinit:這一步是調度器的初始化操作,它會設置GOMAXPROCS的大小,這里的大小不能超過它的上限256,并創建設置好對應數量的P,當然這些P都處于閑置狀態;然后,將這些創建好的P都存放到sched中pidle所關聯的閑置列表中。

Step2: 程序會繼續執行runtime.newproc來創建程序的第一個goroutine,而這個goroutine會執行runtime.main也就是我們看到的main函數,在這之后main會主動創建一個內核線程M,這個M只用來做系統監控用,這個內核線程與程序中goroutinue的調度有關系。

Step3:在runtime.mstart之后,程序就開始執行了,如果后續需要創建goroutine,就會調用go語句來創建。

2.goroutine創建流程是什么樣子的?

在調用go func()的時候,會調用runtime.newproc來創建一個goroutine,這個goroutine會新建一個自己的棧空間,同時在G的sched中維護棧地址與程序計數器這些信息(備注:這些數據在goroutine被調度的時候會被用到。準確的說該goroutine在放棄cpu之后,下一次在重新獲取cpu的時候,這些信息會被重新加載到cpu的寄存器中。)

創建好的這個goroutine會被放到,它所對應的內核線程M所使用的上下文P中的runqueue中。等待調度器來決定何時取出該goroutine并執行,通常調度是按時間順序被調度的,這個隊列是一個先進先出的隊列。

3.新建的這些goroutine是如何被調度的呢?

goroutine在創建好了之后,調度器會決定何時執行這個goroutine,這個過程就叫做調度。

新建好的goroutine,最開始都會存儲在某一個線程M,所關聯的上下文P的runqueue中,但是在后續的調度中,有些goroutine因為調用了runtime.gosched,會被放到全局隊列中。

線程M的選擇過程,按照下面的順序執行:

1.從M對應的P中的runqueue中取出goroutine,來執行,沒有的話,執行2。

2.從全局隊列里面嘗試取出一個goroutine來執行,有的話,執行!沒有的話,執行3。

3.從其他的線程M的P中,偷出一些goroutine來執行,偷失敗了,執行4。(備注:這里偷的話,一偷就偷一半,使用的算法叫做work stealing。)

4.線程M發現無事可做,就去休息了,也就是線程的sleep,它等待被喚醒。

4.運行中的goroutine是怎么停止的呢?一旦被停止了的話,那排隊在它后面的goutinue該怎么辦?

講完了goroutine的調度之后,我們便要考慮一個問題,正在被執行的goroutine何時停止,停止了之后會發生什么?而掛在M對應的P后面的runqueue中的goroutine該怎么辦?

情況1:runtime·park

當調用了runtime·park函數之后,goroutine會被設置成waiting狀態,線程M會放棄它自身關聯的上下文P,而系統會分配一個新的線程M1來接管這個上下文P,(備注:當然這里面的M1也有可能是本來就創建好的,處于閑置狀態中的)。

原來的線程M0則會與上下文斷開連接,M0因為無事可做,就去sleep了,等待下次被喚醒。如下圖所示:

channel的讀寫操作,定時器中,網絡poll等都有可能park goroutine。

情況2:runtime·gosched

調用runtime·gosched函數也可以讓當前goroutine放棄cpu,這種情況下會將goroutine設置成runnable,放置到全局隊列中。備注:這個也就是為什么全局變量的queue里面會有goroutine的原因。

5.goroutine被喚醒之后,會做什么?

goroutine處于waiting狀態的話,在調用runtime·ready函數之后,會被喚醒,喚醒的goroutine會被重新放到,M對應的上下文所對應的runqueue中,等待被調度。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

余姚市| 当涂县| 都安| 福贡县| 广西| 榕江县| 巴彦淖尔市| 和政县| 买车| 东平县| 新竹市| 县级市| 南靖县| 军事| 盘山县| 边坝县| 林芝县| 泽州县| 丹阳市| 龙海市| 石门县| 洪湖市| 武城县| 西峡县| 栖霞市| 镇平县| 绥棱县| 科技| 西乡县| 平江县| 巴东县| 衡水市| 新源县| 云浮市| 托克托县| 苍南县| 富顺县| 闻喜县| 黎川县| 兴海县| 手游|