协程实现原理-源码分析

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扫描

5.G里面重要的成员

1.stack:当前g使用的栈空间
2.stackguard0:检查当前栈空间是否有足够的值,低于这个值就扩张栈,0是go代码使用的
3.stackguard1:检查栈空间是否有足够的值,如果低于这个值就会扩张栈,1是原生代码使用的
4.m:对应g当前的m
5.sched:g的调度数据,当g中断时会保存当前的pc,rsp等值到这里,恢复运行时使用这里的值
6.atomicstatus:g当前的状态
7.schedlink:下一个g,当g在链表结构中会使用
8.preempt:g是否被抢占中
9.lockedm:g是否要求要回到这个M执行,有时g中断之后会要求使用原来的m来执行

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.

8.M里面重要的成员

1 .g0用于调度特殊的g,调度和执行系统时会切换到这个g
2.curg:当前运行的g
3.p:当前拥有的p
4.nextp:唤醒m时,m会有这个p
5.park:M休眠时使用的信号量,唤醒M时会通过他唤醒
6.schedllink:下一个m,当m在链表结构中会使用
7.mache:分配内存时使用的本地分配器,和p.mache一样
8.lockedg:lockedm的对应值

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会重新变成运行中

9.p里面重要的值

1.status:p当前的状态
2.link:下一个p,当p在链表结构中会使用
3.m:拥有这个p的m
4.mache:分配内存时使用的本地分配器
5.runqhead:本地运行队列的出队序号
6.runqtail:本地运行队列的入队序号
7.gfree:G的自由列表,保存为_Gdead后可以复用g的实例
8.gcBgMarkWorker:后台CG的worker函数,如果它存在M会优先执行他
9.gcw:GC的本地功作队列

本地运行队列

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

全局队列

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

M0和G0

1.go中有特殊的M和G,分别是M0和G0
2.m0是骑宠程序后的主线程,这个m对应的实例会在全局变量m0中,不需要再heap上分配
3.m0负责执行初始化操作和启动第一个g,之后m0就和其他的m一样了
4.g0仅是负责调度的g,g0不指向任何可执行的函数,每个m都会有一个自己的g0
5.在调度或者系统调用的时候会使用g0的栈空间,全局变量的g0是m0的g0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容