網(wǎng)站首頁 編程語言 正文
1. 調(diào)度器scheduler的作用
我們都知道,在Go語言中,程序運行的最小單元是gorouines。
然而程序的運行最終都是要交給操作系統(tǒng)來執(zhí)行的,以Java為例,Java中的一個線程對應(yīng)的就是操作系統(tǒng)中的線程,以此來實現(xiàn)在操作系統(tǒng)中的運行。在Go中,gorouines比線程更輕量級,其與操作系統(tǒng)的線程也不是一一對應(yīng)的關(guān)系,然而,最終我們想要執(zhí)行程序,還是要借助操作系統(tǒng)的線程來完成,調(diào)度器scheduler的工作就是完成gorouines到操作系統(tǒng)線程的調(diào)度。
2. GMP模型
當我們運行go fun(){}
時,會生成一個g,優(yōu)先放置在創(chuàng)建他的p的本地隊列中,如果本地隊列已滿,那么會放置在全局隊列中。
g的運行需要借助p與m,p是執(zhí)行器,只有獲得p的g才能執(zhí)行,p的執(zhí)行需要掛在m上,m對應(yīng)的是操作系統(tǒng)中的線程,p的數(shù)量與CPU的核數(shù)相同。
goroutine運行所需要的上下文信息都是存放在g的數(shù)據(jù)結(jié)構(gòu)當中的,所以g可以依靠任意的p或者m執(zhí)行,而對于操作系統(tǒng)而言,其并不能看到p與g的調(diào)度過程,這些過程對于操作系統(tǒng)線程來說都是連續(xù)的,所以省去了線程上下文切換的開銷。
g的數(shù)據(jù)結(jié)構(gòu)如下所示:
type g struct { stack stack // g自己的棧 m *m // 執(zhí)行當前g的m sched gobuf // 保存了g的現(xiàn)場,goroutine切換時通過它來恢復 atomicstatus uint32 // g的狀態(tài)Gidle,Grunnable,Grunning,Gsyscall,Gwaiting,Gdead goid int64 schedlink guintptr // 下一個g, g鏈表 preempt bool //搶占標記 lockedm muintptr // 鎖定的M,g中斷恢復指定M執(zhí)行 gopc uintptr // 創(chuàng)建該goroutine的指令地址 startpc uintptr // goroutine 函數(shù)的指令地址 }
p的數(shù)據(jù)結(jié)構(gòu)如下所示:
type p struct { id int32 status uint32 // 狀態(tài) link puintptr // 下一個P, P鏈表 m muintptr // 擁有這個P的M mcache *mcache // P本地runnable狀態(tài)的G隊列 runqhead uint32 runqtail uint32 runq [256]guintptr runnext guintptr // 一個比runq優(yōu)先級更高的runnable G // 狀態(tài)為dead的G鏈表,在獲取G時會從這里面獲取 gFree struct { gList n int32 } gcBgMarkWorker guintptr // (atomic) gcw gcWork }
m的數(shù)據(jù)結(jié)構(gòu)如下所示:
type m struct { g0 *g // g0, 每個M都有自己獨有的g0 curg *g // 當前正在運行的g p puintptr // 當前用于的p nextp puintptr // 當m被喚醒時,首先擁有這個p id int64 spinning bool // 是否處于自旋 park note alllink *m // on allm schedlink muintptr // 下一個m, m鏈表 mcache *mcache // 內(nèi)存分配 lockedg guintptr // 和 G 的lockedm對應(yīng) freelink *m // on sched.freem }
通過gmp模型,我們能解決gorouines到操作系統(tǒng)線程的映射問題,gorouines之間的切換是在用戶態(tài)完成的,在操作系統(tǒng)的視角來看,線程的上下文切換并不頻繁,因此就少了很多陷入內(nèi)核的過程,所以有更好的并發(fā)效果。
3. 調(diào)度機制
1)work stealing機制
當一個p上的g執(zhí)行完之后,他會嘗試從其他的p隊列中竊取g來執(zhí)行,以減少操作系統(tǒng)線程的切換動作。
2)hand off機制
這個是針對m來說的,有的時候m可能因為g的信號調(diào)用而被操作系統(tǒng)阻塞,這個時候p就會掛載去另一個m繼續(xù)執(zhí)行可以執(zhí)行的g,當阻塞的m就緒之后,會給p發(fā)信號,召喚他回來繼續(xù)進行后續(xù)操作。
原文鏈接:https://juejin.cn/post/7105048959650889765
相關(guān)推薦
- 2022-12-23 C++類成員函數(shù)中的名字查找問題_C 語言
- 2024-07-13 spring-cloud和spring-cloud-alibaba的關(guān)系
- 2022-06-15 go語言context包功能及操作使用詳解_Golang
- 2022-04-17 Mac使用pandoc 將docx文件轉(zhuǎn)換成html文件 快速實現(xiàn)協(xié)議文件的轉(zhuǎn)換
- 2023-03-23 React?Render?Props共享代碼技術(shù)_React
- 2022-08-27 Python?Pandas聚合函數(shù)的應(yīng)用示例_python
- 2022-07-09 C++超詳細講解auto與nullptr的使用_C 語言
- 2022-08-28 ubuntu安裝samba文件共享
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支