<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Go語言的GPM調度器是什么?

      ??我是平也,這有一個專注Gopher技術成長的開源項目「go home」

      導讀

      相信很多人都聽說過Go語言天然支持高并發,原因是內部有協程(goroutine)加持,可以在一個進程中啟動成千上萬個協程。那么,它憑什么做到如此高的并發呢?那就需要先了解什么是并發模型。

      file

      并發模型

      著名的C++專家Herb Sutter曾經說過“免費的午餐已經終結”。為了讓代碼運行的更快,單純依靠更快的硬件已經無法得到滿足,我們需要利用多核來挖掘并行的價值,而并發模型的目的就是來告訴你不同執行實體之間是如何協作的。

      file

      當然,不同的并發模型的協作方式也不盡相同,常見的并發模型有七種:

      • 線程與鎖
      • 函數式編程
      • Clojure之道
      • actor
      • 通訊順序進程(CSP)
      • 數據級并行
      • Lambda架構

      而今天,我們只講與Go語言相關的并發模型CSP,感興趣的同學可以自行查閱書籍《七周七并發模型》。

      file

      CSP篇

      CSP,全稱Communicating Sequential Processes,意為通訊順序進程,它是七大并發模型中的一種,它的核心觀念是將兩個并發執行的實體通過通道channel連接起來,所有的消息都通過channel傳輸。其實CSP概念早在1978年就被東尼·霍爾提出,由于近來Go語言的興起,CSP又火了起來。

      那么CSP與Go語言有什么關系呢?接下來我們來看Go語言對CSP并發模型的實現——GPM調度模型。

      file

      GPM調度模型

      GPM代表了三個角色,分別是Goroutine、Processor、Machine。

      file

      • Goroutine:就是咱們常用的用go關鍵字創建的執行體,它對應一個結構體g,結構體里保存了goroutine的堆棧信息
      • Machine:表示操作系統的線程
      • Processor:表示處理器,有了它才能建立G、M的聯系

      Goroutine

      Goroutine就是代碼中使用go關鍵詞創建的執行單元,也是大家熟知的有“輕量級線程”之稱的協程,協程是不為操作系統所知的,它由編程語言層面實現,上下文切換不需要經過內核態,再加上協程占用的內存空間極小,所以有著非常大的發展潛力。

      go func() {}()
      

      在Go語言中,Goroutine由一個名為runtime.go的結構體表示,該結構體非常復雜,有40多個成員變量,主要存儲執行棧、狀態、當前占用的線程、調度相關的數據。還有玩大家很想獲取的goroutine標識,但是很抱歉,官方考慮到Go語言的發展,設置成私有了,不給你調用??。

      type g struct {
      	stack struct {
      		lo uintptr
      		hi uintptr
      	} 							// 棧內存:[stack.lo, stack.hi)
      	stackguard0	uintptr
      	stackguard1 uintptr
      
      	_panic       *_panic
      	_defer       *_defer
      	m            *m				// 當前的 m
      	sched        gobuf
      	stktopsp     uintptr		// 期望 sp 位于棧頂,用于回溯檢查
      	param        unsafe.Pointer // wakeup 喚醒時候傳遞的參數
      	atomicstatus uint32
      	goid         int64
      	preempt      bool       	// 搶占信號,stackguard0 = stackpreempt 的副本
      	timer        *timer         // 為 time.Sleep 緩存的計時器
      
      	...
      }
      

      Goroutine調度相關的數據存儲在sched,在協程切換、恢復上下文的時候用到。

      type gobuf struct {
      	sp   uintptr
      	pc   uintptr
      	g    guintptr
      	ret  sys.Uintreg
      	...
      }
      

      Machine

      M就是對應操作系統的線程,最多會有GOMAXPROCS個活躍線程能夠正常運行,默認情況下GOMAXPROCS被設置為內核數,假如有四個內核,那么默認就創建四個線程,每一個線程對應一個runtime.m結構體。線程數等于CPU個數的原因是,每個線程分配到一個CPU上就不至于出現線程的上下文切換,可以保證系統開銷降到最低。

      type m struct {
      	g0   *g 
      	curg *g
      	...
      }
      

      M里面存了兩個比較重要的東西,一個是g0,一個是curg。

      • g0:會深度參與運行時的調度過程,比如goroutine的創建、內存分配等
      • curg:代表當前正在線程上執行的goroutine。

      剛才說P是負責M與G的關聯,所以M里面還要存儲與P相關的數據。

      type m struct {
        ...
      	p             puintptr
      	nextp         puintptr
      	oldp          puintptr
      }
      
      • p:正在運行代碼的處理器
      • nextp:暫存的處理器
      • old:系統調用之前的線程的處理器

      Processor

      Proccessor負責Machine與Goroutine的連接,它能提供線程需要的上下文環境,也能分配G到它應該去的線程上執行,有了它,每個G都能得到合理的調用,每個線程都不再渾水摸魚,真是居家必備之良品。

      file

      同樣的,處理器的數量也是默認按照GOMAXPROCS來設置的,與線程的數量一一對應。

      type p struct {
      	m           muintptr
      
      	runqhead uint32
      	runqtail uint32
      	runq     [256]guintptr
      	runnext guintptr
      	...
      }
      

      結構體P中存儲了性能追蹤、垃圾回收、計時器等相關的字段外,還存儲了處理器的待運行隊列,隊列中存儲的是待執行的Goroutine列表。

      三者的關系

      首先,默認啟動四個線程四個處理器,然后互相綁定。

      file

      這個時候,一個Goroutine結構體被創建,在進行函數體地址、參數起始地址、參數長度等信息以及調度相關屬性更新之后,它就要進到一個處理器的隊列等待發車。

      file

      啥,又創建了一個G?那就輪流往其他P里面放唄,相信你排隊取號的時候看到其他窗口沒人排隊也會過去的。

      file

      假如有很多G,都塞滿了怎么辦呢?那就不把G塞到處理器的私有隊列里了,而是把它塞到全局隊列里(候車大廳)。

      file

      除了往里塞之外,M這邊還要瘋狂往外取,首先去處理器的私有隊列里取G執行,如果取完的話就去全局隊列取,如果全局隊列里也沒有的話,就去其他處理器隊列里偷,哇,這么饑渴,簡直是惡魔啊!

      file

      如果哪里都沒找到要執行的G呢?那M就會因為太失望和P斷開關系,然后去睡覺(idle)了。

      file

      那如果兩個Goroutine正在通過channel做一些恩恩愛愛的事阻塞住了怎么辦,難道M要等他們完事了再繼續執行?顯然不會,M并不稀罕這對Go男女,而會轉身去找別的G執行。

      file

      系統調用

      如果G進行了系統調用syscall,M也會跟著進入系統調用狀態,那么這個P留在這里就浪費了,怎么辦呢?這點精妙之處在于,P不會傻傻的等待G和M系統調用完成,而會去找其他比較閑的M執行其他的G。

      file

      當G完成了系統調用,因為要繼續往下執行,所以必須要再找一個空閑的處理器發車。

      file

      如果沒有空閑的處理器了,那就只能把G放回全局隊列當中等待分配。

      file

      sysmon

      sysmon是我們的保潔阿姨,它是一個M,又叫監控線程,不需要P就可以獨立運行,每20us~10ms會被喚醒一次出來打掃衛生,主要工作就是回收垃圾、回收長時間系統調度阻塞的P、向長時間運行的G發出搶占調度等等。

      詞條解釋

      東尼·霍爾

      東尼·霍爾,英國計算機科學家,圖靈獎得主,他設計了牛氣沖天的快速排序算法、霍爾邏輯以及CSP模型。2011年獲頒約翰·馮諾依曼獎。

      file


      感謝大家的觀看,如果覺得文章對你有所幫助,歡迎關注公眾號「平也」,聚焦Go語言與技術原理。
      關注我

      posted @ 2020-04-17 20:19  MARIOOW  閱讀(1152)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 伊人成人在线视频免费| 欧美日韩一区二区综合| 欧日韩无套内射变态| 亚洲香蕉av一区二区蜜桃| 亚洲精品国产男人的天堂| 国产一区二区三区黄网| 国产免费高清69式视频在线观看| 99久久亚洲综合精品成人网| 久久精品成人无码观看免费| 无码视频一区二区三区| 亚洲色婷婷综合开心网| 国产成人毛片在线视频| 夜夜夜高潮夜夜爽夜夜爰爰| 一本色道久久东京热| 宜兴市| 亚洲中文字幕五月五月婷| 天堂中文最新版在线官网在线| 色多多性虎精品无码av| 四虎在线成人免费观看| 久久精品午夜视频| 亚洲AV日韩AV永久无码电影| 国内精品无码一区二区三区| 欧美三级欧美成人高清| 日韩亚洲中文图片小说| 日韩有码av中文字幕| 国产女人18毛片水真多1| 久久亚洲女同第一区综合| 国产精品自拍中文字幕| 维西| 老鸭窝在线视频| 国产精品99久久免费| 亚洲无av在线中文字幕| 草草浮力影院| 色噜噜亚洲男人的天堂| 国产精品制服丝袜白丝| 91亚洲人成手机在线观看| 亚洲精品国模一区二区| 一个色综合色综合色综合| 亚洲色最新高清AV网站| 亚洲色成人网站www永久下载| 一区二区三区精品偷拍|