Go语言线程与协程之间的关系之GMP模型
1. GMP模型
这里首先给出GMP模型的调度策略. 让大家有一个全局的认识更好
2. G (groutine)
G就是goroutine的意思, 代表了一个协程. 每次go调用的时候,都会创建一个G对象,它包括栈、指令指针以及对于调用goroutines很重要的其它信息,比如阻塞它的任何channel,其主要数据结构:
type g struct {stack stack // 描述了真实的栈内存,包括上下界............. // 中间还有很多部分m *m // 当前G的绑定的msched gobuf // goroutine切换时,用于保存g的上下文 param unsafe.Pointer // 用于传递参数,睡眠时其他goroutine可以设置param,唤醒时该goroutine可以获取atomicstatus uint32stackLock uint32 goid int64 // goroutine的IDwaitsince int64 // g被阻塞的大体时间lockedm *m // G被锁定只在这个m上运行............. // 省略
}
看这个结构我们可以得知, G需要与M进行绑定. 当然最重要的还是sched这个结构体 存储了调度时g的上下文(context)
type gobuf struct {// 保存CPU的rsp寄存器的值sp uintptr// 保存CPU的rip寄存器的值pc uintptr// 记录这个gobuf对象属于那个gg guintptrctxt unsafe.Pointerret sys.Uintreglr uintptrbp uintptr // for framepointer-enabled architectures
}
sp, pc 寄存器的值, 栈指针等等. 记录了上下文
3. M(machine)
M代表了一个线程 . 每次创建一个M的时候,都会有一个底层线程创建;所有的G任务,最终还是依附于M上执行,其主要数据结构:
type m struct {g0 *g // 带有调度栈的goroutinegsignal *g // 处理信号的goroutinetls [6]uintptr // thread-local storagemstartfn func()curg *g // 当前运行的goroutinecaughtsig guintptr p puintptr // 关联的p和执行的go代码nextp puintptrid int32mallocing int32 // 状态spinning bool // m是否out of workblocked bool // m是否被阻塞inwb bool // m是否在执行写屏蔽
}
其中重点要关注的是 g0 和 curg , curg代表的当前执行的groutine协程
另一个是g0,是带有调度栈的goroutine,这是一个比较特殊的goroutine。普通的goroutine的栈是在堆上分配的可增长的栈,而g0的栈是M对应的线程的栈。所有调度相关的代码,会先切换到该goroutine的栈中再执行。也就是说线程的栈也是用的g实现,而不是使用的OS的。
4. P(processor)
执行器或者处理器. 相当于一个管理者. 每一个M必须要绑定一个P. P自身有一个局部本地队列用来保存g. 并且所有的p都共享这一个全局队列
P负责调度goroutine,维护一个本地goroutine队列,M从P上获得goroutine并执行,同时还负责部分内存的管理。
下面的p的局部实现
lock mutexid int32status uint32 // 状态,可以为pidle/prunning/...link puintptrschedtick uint32 // 每调度一次加1syscalltick uint32 // 每一次系统调用加1sysmontick sysmontick m muintptr // 关联的mmcache *mcacheracectx uintptrgoidcache uint64 // goroutine的ID的缓存goidcacheend uint64runqhead uint32 // 头部runqtail uint32 // 尾部// 队列在这呢runq [256]guintptr // 可运行的goroutine的队列runnext guintptr // 下一个运行的g
}
5.调度顺序
下面说一下详细的过程
- go func(){}创建一个新的goroutine
- 这个goroutine会被挑选进入一个P的本地队列, 若是本地队列满了, 那么就进入全局的队列
- 这时M向P要goroutine去执行了. G依附于M上运行,每个M绑定一个P。如果P的本地队列没有G,M会从全局队列寻找G, 如果全局队列也没有G, 那么P会从其他P里面窃取G
- M被操作系统调度到CPU上面执行, G也就执行了, 若是在此期间,M这个线程遇到阻塞或者系统调用, 那么此时P就会与M解绑. 并在M的休眠队列里面唤醒一个新的M与之绑定, 然后再去运行G.
- 若是在此期间是G发生了阻塞, 那么M也会阻塞. 此时M就会与P解绑, 由M1接管P.去运行其他的G. M等待阻塞的返回, 就将G放入全局队列中了, 自己就去休眠了.
- 运行完之后G就会被销毁退出.
5.1 协程调度
5.1.1 主动调度
主动的让出CPU资源, 此时当前协程切换到g0, 取消G与M之间的绑定关系, 再将此G放入全局队列中, 并调用schedule函数开始新一轮的循环
5.1.2 抢占式调度
当某个协程占用CPU时间过长时, go语言调度器就会强制中断执行.并保存上下文等待下次调度
Go语言线程与协程之间的关系之GMP模型相关推荐
- python 协程、进程、线程_Python进程、线程、协程之间的关系
一.从操作系统角度 操作系统处理任务, 调度单位是 进程 和 线程 . 1.进程: 表示一个程序的执行活动 (打开程序.读写程序数据.关闭程序) 2.线程: 执行某个程序时, 该进程调度的最小执行单位 ...
- 进程、线程、协程之间的关系
一.进程: 是系统进行资源分配和调度的基本单位,是操作系统结构的基础,是程序的实体:每个进程都有它自己的地址空间(文本区域.数据区域.堆栈): 二.线程: 是程序执行流的最小单元,一个标准的线程由线程 ...
- python协程和线程_线程和协程之间的区别
线程和协程之间的区别很大,甚至大过进程和线程之间的区别.线程建立在进程之上,协程建立在线程之上.那么协程是什么呢? 协程是一段计算机程序,它一般是一个协作类型的子程序,执行时允许暂停和恢复.协程非常适 ...
- python协程和线程区别_python中的线程和协程之间有什么区别
一.首先我们来了解一下线程和协程的概念1.线程线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源( ...
- 进程、线程和协程之间的区别和联系
文章目录 一.进程 二.线程 三.进程和线程的区别与联系 四.一个形象的例子解释进程和线程的区别 五.进程/线程之间的亲缘性 六.协程 一.进程 进程,直观点说,保存在硬盘上的程序运行以后,会在内 ...
- java协程和线程_Kotlin中的线程和协程之间的区别
由于我仅在JVM上使用协程,因此我将讨论JVM后端,也有Kotlin本机和Kotlin JavaScript,但是这些Kotlin后端不在我的讨论范围之内. 因此,让我们开始将Kotlin协程与其他语 ...
- kotlin 子线程睡3秒_Kotlin中线程和协程之间的区别
Ruslan.. 47 由于我只在JVM上使用协同程序,我将讨论JVM后端,还有Kotlin Native和Kotlin JavaScript,但Kotlin的这些后端超出了我的范围. 让我们首先将K ...
- handler回调主线程_Android使用Handler实现子线程与子线程、子线程与主线程之间通信...
转载:https://blog.csdn.net/shaoenxiao/article/details/54561753 今天这篇文章只讲一下怎么使用Handler实现子线程与子线程之间.子线程与主线 ...
- 请你说说进程、线程、纤程之间的区别?
其他链接:JAVA相关的深度技术博客链接 相信很多小伙伴们在面试的时候,面试官都会提这样的一个问题. 请你说说什么是进程,什么是线程,两者有什么区别? 很多小伙伴可能会直接说,进程就是一个个后台程序, ...
最新文章
- JavaScript 二进制的 AST
- Windows原生运行Linux的技术细节
- c++ 使用vs2010调用 win32api
- 数据挖掘流程(二):数据预处理
- sprint周期总结
- 男程序员怎么保养皮肤【护肤】?
- IOS 本地推送 IOS10.0以上 static的作用 const的作用
- 百度十亿级流量的搜索前端,是怎么做架构升级的?
- 代码提交本地代码和远程代码不同步问题(笔记)
- EMD算法原理分解信号
- java.lang.IllegalStateException: Ambiguous mapping found. Cannot map ' ' bean method
- 解读制造业数字化转型的现状及发展趋势
- java 格式化日期(DateFormat)
- java语言开发的中间件名称,值得收藏!
- 三步完美完成wordpress外链跳转
- ubuntu如何查看java版本_Ubuntu 如何查看安装的 JDK
- 鸿蒙试炼多少可以单挑,知己知彼《灭神》单挑虚无之地大BOSS
- java ssl 双向认证_Java实现SSL双向认证的方法
- JS代码:身份证号EMAIL检验
- There is no getter/setter for property named ‘XXX‘ in ‘class com.XXX‘