亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
GMP是什么
處理器P
作用
源碼解析
線程M與處理器P是如何協(xié)作的?
新建的協(xié)程該分配到哪?
結(jié)語
首頁 后端開發(fā) Golang 深入淺析Go語言中要有GMP調(diào)度模型的原因

深入淺析Go語言中要有GMP調(diào)度模型的原因

Apr 14, 2023 pm 03:26 PM
go 后端

Go為什么要有GMP調(diào)度模型?下面本篇文章給大家介紹一下Go語言中要有GMP調(diào)度模型的原因,希望對大家有所幫助!

深入淺析Go語言中要有GMP調(diào)度模型的原因

GMP調(diào)度模型是Go的精髓所在,它合理地解決了多線程并發(fā)調(diào)度協(xié)程的效率問題。

GMP是什么

首先得清楚,GMP各代指什么東西。

  • G: Goroutine的縮寫,指協(xié)程,運(yùn)行在線程上。
  • M: Machine的縮寫,即thead,線程,循環(huán)的調(diào)度協(xié)程并執(zhí)行。
  • P: Processor的縮寫,指處理器,將協(xié)程儲存到本地隊(duì)列,并為線程提供未休眠的可用的協(xié)程,

線程M各自持有一個(gè)處理器P,當(dāng)要獲取協(xié)程時(shí)優(yōu)先從P中獲取,于是GMP模型圖解如下:

image.png

大致流程是,線程M從P的隊(duì)列中獲取協(xié)程,如果獲取不到,就會(huì)從全局隊(duì)列中去競爭鎖來獲取。

處理器P

協(xié)程G和線程M結(jié)構(gòu)在前幾篇已經(jīng)講解了,這里解析一下處理器P。

作用

處理器P儲存著一批協(xié)程,使得線程M可以無鎖的從中獲取協(xié)程,而無需與其他線程去競爭全局隊(duì)列中的協(xié)程,從而提高調(diào)度協(xié)程效率。

源碼解析

p結(jié)構(gòu)體源碼在src\runtime\runtime2.go中,這里展示部分重要字段。

type p struct {
   ...
   m           muintptr   // back-link to associated m (nil if idle)
   // Queue of runnable goroutines. Accessed without lock.
   runqhead uint32
   runqtail uint32
   runq     [256]guintptr
   runnext guintptr
   ...
}
  • m為處理器p所屬的線程
  • runq是一個(gè)儲存協(xié)程的隊(duì)列
  • runqhead,runqtail表示隊(duì)列的頭尾指針
  • runnext指向下一個(gè)可運(yùn)行的協(xié)程

image.png

線程M與處理器P是如何協(xié)作的?

src\runtime\proc.go中,有一個(gè)schedule方法,這是線程運(yùn)行的第一個(gè)函數(shù)。這函數(shù)中,線程需要獲取到可運(yùn)行的協(xié)程,代碼如下:

func schedule() {    
    ...
    // 尋找一個(gè)可運(yùn)行的協(xié)程
    gp, inheritTime, tryWakeP := findRunnable() 
    ...
}
func findRunnable() (gp *g, inheritTime, tryWakeP bool) {
    // 從本地隊(duì)列中獲取協(xié)程
    if gp, inheritTime := runqget(pp); gp != nil {
       return gp, inheritTime, false
    }

    // 本地隊(duì)列拿不到則從全局隊(duì)列中獲取協(xié)程
    if sched.runqsize != 0 {
       lock(&sched.lock)
       gp := globrunqget(pp, 0)
       unlock(&sched.lock)
       if gp != nil {
          return gp, false, false
       }
    }
}

從本地隊(duì)列中獲取協(xié)程

func runqget(pp *p) (gp *g, inheritTime bool) {
   next := pp.runnext // 隊(duì)列中下一個(gè)可運(yùn)行的協(xié)程
   if next != 0 && pp.runnext.cas(next, 0) {
      return next.ptr(), true
   }
   ...
}

那如果本地隊(duì)列和全局隊(duì)列中都沒有協(xié)程了怎么辦呢,難道就讓線程這么閑著?

這時(shí)候處理器P就會(huì)任務(wù)竊取,從其他線程的本地隊(duì)列中竊取一些任務(wù),美其名曰分擔(dān)其他線程的壓力,還提高了自己線程的利用率。

源碼在src\runtime\proc.go\stealWork中,感興趣可以看看。

新建的協(xié)程該分配到哪?

新建的協(xié)程該分配到本地還是全局隊(duì)列呢,得分情況:

  • Go認(rèn)為新協(xié)程的優(yōu)先級高,于是先尋找本地隊(duì)列放入,而且還插隊(duì)。
  • 本隊(duì)隊(duì)列滿了才放入全局隊(duì)列。

實(shí)際流程為:

  1. 隨機(jī)尋找P
  2. 將新協(xié)程放入P的runnext中,意味著下一個(gè)就運(yùn)行該協(xié)程,插隊(duì)了
  3. 若P的協(xié)程滿了,則放入全局隊(duì)列

源碼在src\runtime\proc.go\newproc函數(shù)中。

// Create a new g running fn.
// Put it on the queue of g's waiting to run.
// The compiler turns a go statement into a call to this.
func newproc(fn *funcval) {
   gp := getg()
   pc := getcallerpc()
   systemstack(func() {
      newg := newproc1(fn, gp, pc) // 創(chuàng)建新協(xié)程

      pp := getg().m.p.ptr()
      runqput(pp, newg, true) // 尋找本地隊(duì)列放入

      if mainStarted {
         wakep()
      }
   })
}

結(jié)語

本篇初步介紹了GMP調(diào)度模型,具體介紹了處理器P以及線程M獲取協(xié)程的方式。

處理器P解決了多線程互斥獲取協(xié)程的問題,提高調(diào)度協(xié)程的效率,但是不管協(xié)程在本地還是全局隊(duì)列,目前看來還只是順序執(zhí)行,那Go是如何實(shí)現(xiàn)協(xié)程異步并發(fā)執(zhí)行的呢?咱下一篇繼續(xù)分析(雖然沒什么人看...)。

推薦學(xué)習(xí):Golang教程

以上是深入淺析Go語言中要有GMP調(diào)度模型的原因的詳細(xì)內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
Switch語句如何運(yùn)行? Switch語句如何運(yùn)行? Jul 30, 2025 am 05:11 AM

Go的switch語句默認(rèn)不會(huì)貫穿執(zhí)行,匹配到第一個(gè)條件后自動(dòng)退出。1.switch以關(guān)鍵字開始并可帶一個(gè)值或不帶值;2.case按順序從上到下匹配,僅運(yùn)行第一個(gè)匹配項(xiàng);3.可通過逗號列出多個(gè)條件來匹配同一case;4.不需要手動(dòng)添加break,但可用fallthrough強(qiáng)制貫穿;5.default用于未匹配到的情況,通常放最后。

如何從GO中筑巢的循環(huán)中斷 如何從GO中筑巢的循環(huán)中斷 Jul 29, 2025 am 01:58 AM

在Go中,要跳出嵌套循環(huán),應(yīng)使用標(biāo)簽化break語句或通過函數(shù)返回;1.使用標(biāo)簽化break:將標(biāo)簽置于外層循環(huán)前,如OuterLoop:for{...},在內(nèi)層循環(huán)中使用breakOuterLoop即可直接退出外層循環(huán);2.將嵌套循環(huán)放入函數(shù)中,滿足條件時(shí)用return提前返回,從而終止所有循環(huán);3.避免使用標(biāo)志變量或goto,前者冗長易錯(cuò),后者非推薦做法;正確做法是標(biāo)簽必須位于循環(huán)之前而非之后,這是Go語言中跳出多層循環(huán)的慣用方式。

使用上下文軟件包進(jìn)行取消和超時(shí) 使用上下文軟件包進(jìn)行取消和超時(shí) Jul 29, 2025 am 04:08 AM

USECONTEXTTOPROPAGATECELLATION ANDDEADEADLINESACROSSGOROUTINES,ENABLINGCOOPERATIVECELLATIONININHTTPSERVERS,背景任務(wù),andChainedCalls.2.withContext.withContext.withCancel(),CreatseAcancellableBableBablebableBableBableBablebableContExtandAndCandExtandCallCallCancelLcancel()

建立表演者為第三方API的客戶 建立表演者為第三方API的客戶 Jul 30, 2025 am 01:09 AM

使用專用且配置合理的HTTP客戶端,設(shè)置超時(shí)和連接池以提升性能和資源利用率;2.實(shí)現(xiàn)帶指數(shù)退避和抖動(dòng)的重試機(jī)制,僅對5xx、網(wǎng)絡(luò)錯(cuò)誤和429狀態(tài)碼重試,并遵守Retry-After頭;3.對靜態(tài)數(shù)據(jù)如用戶信息使用緩存(如sync.Map或Redis),設(shè)置合理TTL,避免重復(fù)請求;4.使用信號量或rate.Limiter限制并發(fā)和請求速率,防止被限流或封禁;5.將API封裝為接口,便于測試、mock和添加日志、追蹤等中間件;6.通過結(jié)構(gòu)化日志和指標(biāo)監(jiān)控請求時(shí)長、錯(cuò)誤率、狀態(tài)碼和重試次數(shù),結(jié)合Op

如何在Go中正確復(fù)制切片 如何在Go中正確復(fù)制切片 Jul 30, 2025 am 01:28 AM

要正確復(fù)制Go中的切片,必須創(chuàng)建新的底層數(shù)組,而不是直接賦值;1.使用make和copy函數(shù):dst:=make([]T,len(src));copy(dst,src);2.使用append與nil切片:dst:=append([]T(nil),src...);這兩種方法都能實(shí)現(xiàn)元素級別的復(fù)制,避免共享底層數(shù)組,確保修改互不影響,而直接賦值dst=src會(huì)導(dǎo)致兩者引用同一數(shù)組,不屬于真正復(fù)制。

如何將template.parsefs與GO嵌入? 如何將template.parsefs與GO嵌入? Jul 30, 2025 am 12:35 AM

使用template.ParseFS與embed包可將HTML模板編譯進(jìn)二進(jìn)制文件。1.導(dǎo)入embed包并用//go:embedtemplates/.html將模板文件嵌入embed.FS變量;2.調(diào)用template.Must(template.ParseFS(templateFS,"templates/.html"))解析所有匹配的模板文件;3.在HTTP處理器中通過tmpl.ExecuteTemplate(w,"home.html",nil)渲染指定

Jul 30, 2025 am 02:51 AM

Go使用time.Time結(jié)構(gòu)體處理日期和時(shí)間,1.格式化和解析使用參考時(shí)間“2006-01-0215:04:05”對應(yīng)“MonJan215:04:05MST2006”,2.創(chuàng)建日期使用time.Date(year,month,day,hour,min,sec,nsec,loc)并指定時(shí)區(qū)如time.UTC,3.時(shí)區(qū)處理通過time.LoadLocation加載位置并用time.ParseInLocation解析帶時(shí)區(qū)的時(shí)間,4.時(shí)間運(yùn)算使用Add、AddDate和Sub方法進(jìn)行加減和計(jì)算間隔,

符文是什么? 符文是什么? Jul 31, 2025 am 02:15 AM

Aruneingoisaunicodecodepointrepointreporentedasanint32,使用了tocortloctlyhandhandlenternationCharacters; 1. userunesInesinSteadofbyTestoavoidSplittingMulti-bydeunicodecharacters; 2. 2. loopoverstringswithrangetogetrogetogetogetrogeTringsWithRangetogetrounes,notbyters; 3.converteranemantermaneflymantofelymanteranemantermanterantoflyman [] []

See all articles