协程实现原理-源码分析

aside section ._1OhGeD · · 1017 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

G

1 .goroutine的新建,休眠,恢复,停止都会受到go运行时的管理
2 .goroutine执行异步操作时,等操作完成之后在恢复,不会占用系统线程
3 .goroutine新建或者恢复会添加到运行队列,等待M取出并运行
4 .G的状态

1 .空闲中:idle:G刚创建,没有初始化
2 .待运行:runnable:g正在运行队列中,等待M取出并运行
3 .运行中:running:M正在运行这个G,这时M会拥有一个P
4 .系统调用:syscall:表示这个M这个在运行这个g发起的系统调用,这时M并不拥有p
5 .等待中waiting:表示g在等待某些条件完成。此时g不在运行也不再运行队列中,可能在channel等待队列中
6 .已终止:dead,表示G未被使用,可能已经执行完毕
7 .栈复制中:copystack,表示g正在获取一个新的栈空间并把原来的内容复制过去,用于防止GC扫描

M

1 .在当前golang中等于系统线程
2 .m运行以下代码:go代码,即goroutine,M运行go代码需要一个p提供环境。原生代码,例如阻塞的syscall.m运行原生代码不需要p
3 .m会从运行队列中取出G,然后运行G,如果G运行完毕或者进入休眠状态,则从队列中取出下一个g运行,周而复始。
4 .有时g需要调用一些无法避免阻塞的原生代码,这个时候m会释放持有的p并进入阻塞状态,其他m会取得这个p并继续运行队列中的G
5 .go需要保证有足够多的m来运行G,不会让cpu闲着,也会保证m的数量不能太多
6 .m的状态

1 .自旋中:m正在从运行队列获取g,这个时候m会拥有一个p,是否唤醒或者创建新的m取决于当前自旋中的m的数量
2.执行go代码:m正在执行go代码,这时m会有一个p
3.执行原生代码:m正在执行原生代码或者阻塞的syscall,这时m没有p
4.休眠中:m发现无待运行的g会进入休眠,并添加到空闲m链表中,这时m没有p
5.

7.空闲m链表

1.进入休眠的M会等待一个信号量m.park,唤醒休眠的m会使用这个信号量
2.go需要保证有足够的m可以运行g
3.入队待运行的G之后,如果当前无自旋的M但是有空闲的P,就唤醒或者新建一个M
4.M离开自旋状态并运行出队的G时(出队是指从本地或者全局队列中出队在m上运行),如果当前无自选的但是有空闲的p,就唤醒或者新建一个m
5.当m离开自旋状态准备休眠时,会在离开后再次检查所有运行队列,如果有待运行的g重新进入自旋状态
6.

p

1.代表M运行G需要的资源
2.p的数量默认为是cpu核数,但是可以动态设置
3.p就是控制go代码并行度的机制。
4.如果p的数量等于1,那就证明当前最多有一个线程来执行go代码
5.执行原生代码的线程数量是不受p的控制
6.因为同一个时间只有一个m可以有p,此时p的数据都是锁自由的,所以读写这些数据非常效率高
7.p的状态

1.空闲中idle:当m发现无待运行的G时会进入休眠,这时M拥有的p会变为空闲并加入到空闲p链表中
2.运行中running:当拥有一个p之后,这个p的状态就会变为运行中,M执行G会使用这个p中的资源
3.系统调用中:syscall当go调用原生代码的时候,原生代码反过来又调用go代码时,使用的p会变成此状态
4.GC停止中:当gc停止了整个世界时,p会变为这个状态
5.dead已停止:当p的数量在运行时改变,且数量减少时多余的p会变为这个状态

8.空闲p链表

1.当本地的运行队列中的所有G都运行完毕,又不能从其他地方拿到G时
2.拥有p的M会释放p并进入休眠状态,释放的p会变为空闲状态并加入空闲p链表中,空闲p链表保存在全局变量sched中
3.下次待运行的G入队时如果发现有空闲的p,但是有没有自旋中的M会唤醒或者新建一个m,m会拥有这个p.p会重新变成运行中

本地运行队列

1.在go中有多个运行队列可以保存运行的G,分别是p的本地队列和全局队列
2.入队待运行的G,会优先添加到当前p的本地队列,m获取待运行的G时也会优先从拥有的p的本地队列获取
3.本地运行队列有数量上限,超过256个会入队到全局队列
4.本地队列入队和出队不需要使用线程锁
5.本地队列是一个环形队列,长256的数组和两个序号组成
6.当m从p的本地运行队列获取G时,如果发现本地队列为空,会从其他的p盗取一半的G过来

全局队列

1.全局队列保存在全局变量sched中,全局运行队列入队和出队需要使用线程锁


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:aside section ._1OhGeD

查看原文:协程实现原理-源码分析

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1017 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传