成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go Scheduler 的 GMP 模型

開發(fā)
Go 為了自身 goroutine 執(zhí)行和調度的效率,自身在 runtime 中實現(xiàn)了一套 goroutine 的調度器。

寫在前面

Go 為了自身 goroutine 執(zhí)行和調度的效率,自身在 runtime 中實現(xiàn)了一套 goroutine 的調度器,下面通過一段簡單的代碼展示一下 Go 應用程序在運行時的 goroutine,方便大家更好的理解。

The Go scheduler is part of the Go runtime, and the Go runtime is built into your application

for i := 0; i < 4; i++ {
go func() {
time.Sleep(time.Second)
}()
}
fmt.Println(runtime.NumGoroutine())

上面這段代碼的輸出為:5。說明當前這個應用程序中存在 goroutine 的數量是 5,事實上也符合我們的預期。那么問題來了,這 5 個 goroutine 作為操作系統(tǒng)用戶態(tài)的基本調度單元是無法直接占用操作系統(tǒng)的資源來執(zhí)行的,必須經過內核級線程的分發(fā),這是操作系統(tǒng)內部線程調度的基本模型,根據用戶級線程和內核級線程的對應關系可以分為 1 對 1,N 對 1 以及 M 對 N 這三種模型,那么上述的 5 個 goroutine 在內核級線程上是怎么被分發(fā)的,這就是 Go語言的 goroutine 調度器決定的。

圖片

GMP 模型

整個 goroutine 調度器的實現(xiàn)基于 GMP 的三級模型來實現(xiàn)。

  • G:goroutine
  • M:內核級線程,運行在操作系統(tǒng)的核心態(tài)。在 Go 中支持最大的 M 的數量是 10000,但是操作系統(tǒng)中通常情況是不可以創(chuàng)建這么多的線程。
  • P:processor,可以理解成一個等待分發(fā)給 M 調度執(zhí)行的 goroutine 隊列。P的個數是由 runtime 的 GOMAXPROCS 來決定的。

M 和 P 存在一一對應的綁定關系。大致的結構圖如下所示:

圖片

goroutine 之旅

通常情況下,我們在代碼中執(zhí)行 go func(){}后,GMP 模型是如何工作的?通過一個詳細的圖來展示一下。

圖片

  1. 首先創(chuàng)建一個新的 goroutine
  2. 如果本地的局部隊列中有足夠的空間可以存放,則放入局部隊列中;如果局部隊列滿,則放入一個全局隊列(所有的 M 都可以從全局隊列中拉取 G 來執(zhí)行)
  3. 所有的 G 都必須在 M 上才可以被執(zhí)行,M 和 P 存在一一綁定的關系,如果 M 綁定的 P 中存在可以被執(zhí)行的 G,則從 P 中拉取 G 來執(zhí)行;如果 P 中為空,沒有可執(zhí)行的 G,則  M 從全局隊列中拉取;如果全局隊列也為空,則從其他的 P 中拉取 G
  4. 為 G 的運行分配必要的資源,等待 CPU 的調度
  5. 分配到 CPU,執(zhí)行 func(){}

調度策略

整個 goroutine 調度器最重要的調度策略是:復用,避免頻繁的資源創(chuàng)建和銷毀,最大限度的提升系統(tǒng)的吞吐量和并發(fā)程度。這也是操作系統(tǒng)進行線程調度的終極目標。復用(reuse)也是很多「池化技術」的基礎。

圍繞著這一原則,goroutine 調度器在以下幾個方面進行調度策略的優(yōu)化。

  1. 工作隊列的竊取機制:這個跟 Java 中的 ForkJoin Pool 的竊取機制同一原理,都是當線程 M 空閑時,從其他繁忙的隊列 P 中"竊取"任務 G 過來執(zhí)行,而不是銷毀空閑的 M。因為線程的創(chuàng)建和銷毀是需要消耗系統(tǒng)資源的,避免線程的頻繁創(chuàng)建和銷毀可以極大的提升系統(tǒng)的并發(fā)程度。
  2. 交接機制:當線程M被阻塞的時候,M 會主動將 P 交接給其他空閑的 M。

另外,在 go 的 1.14 版本中,go 語言的技術團隊嘗試在調度器中添加了可搶占的技術[https://github.com/golang/go/issues/24543]

  1. 搶占技術的出現(xiàn)一方面解決了線程 M 在執(zhí)行計算密集型任務時長時間占用 CPU,導致與之綁定的 P 上的其他 G 得不到執(zhí)行而造成的"饑餓現(xiàn)象";
  2. 另一方面,搶占技術的出現(xiàn)對 GC 來講解決 GC 時可能出現(xiàn)的 deadLock,相關的 issue 見:關于 GC 時 tight loops 應該可以被搶占的討論
    [https://github.com/golang/go/issues/10958]

最開始的 MG 模型

在 go 語言的早期,goroutine 調度器的模型并不是 GMP,而是 GM。整個調度器維護一個全局的 G 的等待隊列,所有的 M 從這個全局的隊列中拉取 G 來執(zhí)行,在 go1.1 中將這種模型直接干掉,取而代之的是現(xiàn)在的 GMP 模型,在 GM 模型的基礎上增加 P 局部隊列。官方之所有這么這么做,原因有二:

  1. 全局的 G 等待隊列,不同的M從隊列里取 G 都需要加鎖,鎖的粒度很大,嚴重制約了系統(tǒng)并發(fā)能力的提升;
  2. 沒有局部隊列,那么當線程在執(zhí)行 IO 密集型操作時,M 阻塞在 IO 操作上,對應的 G 也沒有辦法得到執(zhí)行(GMP 中可以將 G 交接給其他的 M 執(zhí)行),因此 GM 模型在應對 IO 密集型任務時性能表現(xiàn)低下。
責任編輯:龐桂玉 來源: 字節(jié)跳動技術團隊
相關推薦

2024-07-30 12:24:23

2024-09-02 09:00:59

2023-05-22 09:27:11

GMPGolang

2023-08-21 07:34:37

GolangGMP

2021-10-26 07:42:49

Go線程數GMP

2022-12-06 08:30:06

SchedulerReact

2025-05-26 00:05:00

2023-03-06 00:27:02

Kubernetesscheduler系統(tǒng)

2021-07-06 14:47:30

Go 開發(fā)技術

2024-02-19 07:40:10

2021-06-02 09:23:57

Go開發(fā)內存

2024-06-27 07:56:49

2023-11-29 09:29:48

Kuberneteskube

2021-01-29 08:22:03

調度器Yarn架構

2024-06-06 09:47:56

2023-08-10 08:01:36

RDB數據AOF

2023-03-26 23:47:32

Go內存模型

2017-05-08 11:37:41

Go調度器源碼分析程序
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人在线视频网站 | 国产在线精品一区二区三区 | 亚洲电影一区二区三区 | 国产精品99久久久久久久久久久久 | 中文字幕av在线一二三区 | 99免费在线视频 | 欧美精品1区 | 国产精品九九九 | 成人激情视频在线播放 | 久久久国产一区 | 免费看日韩视频 | 综合婷婷 | 小视频你懂得 | 91一区二区三区在线观看 | 亚洲欧美在线观看 | 亚洲欧美中文日韩在线v日本 | 黄片毛片在线观看 | 亚洲一区二区三区在线 | 男女视频在线观看免费 | 99精品国产一区二区青青牛奶 | 91精品一区| 日韩av成人 | www.久久久久久久久久久久 | 亚洲国产成人一区二区 | 看片91 | 另类视频在线 | 亚洲欧美视频 | 日韩毛片免费看 | 国产日韩精品一区二区三区 | 欧美国产精品 | 亚洲日本视频 | 狠狠操狠狠操 | 久久精品国产一区老色匹 | 日韩中文av在线 | 中文在线a在线 | 久久久久成人精品免费播放动漫 | 久久精品国产99国产精品亚洲 | 99久久久无码国产精品 | 久久久久久久久久影视 | 久久国产视频网站 | 亚洲激情自拍偷拍 |