自己对go协程的理解

前言:

下面是自己看了很多资料后总结下来的不一定对.因为能力还不够,还不能够深入源码一探究竟.
如果自己哪里不对,希望可以留言.一起讨论一下.

进程线程协程的理解

1. 进程 :是计算机进行资源分配的最小单位,上下文开销很大,进程之间数据是隔离的.
2. 线程 :是计算机调度的最小单位,是计算机运行的基本单元.(个人理解 可以把线程理解成是共享堆的进程),上
下文调度相对于进程来说要轻量(因为线程之间调度不需要切换进程资源)
3. 协程 :是用户态的一种轻量的线程,协程的调度完全由用户控制. 不需要内核参与,所以速度很快.

go协程模型和特点

协作顾名思义是互相协作的,但是go的协程不完全是互相协作的,还会相互抢占.go底层是基于gmp模型实现的协程调度.
M: 系统真正的线程.m的任务就是想办法去找到可以运行的g.并且运行它
P: G的集合,有个g的链表.一般会和m绑定.m不断运行p上面的g.并且p会存储m上线程的相关信息
G: go的协程真正的实体.代表正在要执行的协程的逻辑和其要运行的上下文.

自己对gmp模型的理解(不一定准确)

大家有没有觉得m->p->g的关系其实就是 计算机->进程->线程的关系. 因为计算机涉及到很多因素的影响,所以对进程
线程之间的调度开销会很大所以go的作者很有创造性的把这个过程在用户态自己模拟一套.正因为如此一些简单的调度都
不需要用到系统来参与,go表示我自己就可以完成了,所以性能要好的很多!

具体GMP是怎么运行的

首先协程实现的功能和线程是一样的,就是让我们能够同时运行多个逻辑的能力(这里指的是并发不是并行).

1. 启动协程: go程序内部都维护了一个 gfree的一个list.每次我们启动一个新的协程的时候 程序不会 
马上就new一个g对象.而是先去gfree里找,如果gfree里面有现成的g对象,就会直接拿来用.如果gfree里面
没有才会去new一个对象,所有的g运行完了都不会直接销毁.而是放到了gfree里.相当于gfree是一个g的对象池.
总而言之go底层g是复用的.

2. 协程绑定p: 当协程被启动后就会优先依附于启动自己的m所绑定的p上,这样很大程度上避免了m与m之间的竞争.
当m上的p的g已经超过了承受范围就会放到全局的g的队列里.与m绑定的p最多只有256个g. 

3. m的运行: m就是不断地运行依附于自己上的p上的g.为了让全局的g队列里也能够被调度到.m每运行61个本地g就会
去全局g队列里拿一个g运行.当m本地的p没有g可以运行的时候也会去全局队列里面拿g运行.当全局队列也没有g的时候.
就会去别的m绑定的p上偷一半g来运行.如果这个时候m还是拿不到g.那么这个m就会陷入睡眠.值得注意的是睡眠m也是
不会被销毁的.防止m被频繁的创建销毁.

go的协程 什么时候调度的,怎么调度的

首先我们需要知道go的协作在什么情况会被调度(就是别的协程抢占)

1. 当协程运行时间过长的时候,那么这个协程在调用非内联函数的时候会被调度:
正式因为有这个特性,go的协程才具有了抢占性,才让goroutine不再是单纯的协程. 首先程序会在启动的时候运行一个
sysmon线程,这个线程负责整个的调度具有上帝视角.sysmon会给所有的p都记录一个已运行的g的数量.每当p运行一个g后
都会加1.如果这个变量没有加1,就说明这个p一直在运行同一个g任务.如果超过了10ms,就给这个g的栈信息上加个标记.
当有了这个标记,这个g在遇到非内联函数的时候就会把自己中断掉,移到当前p的队列尾.

2. 当协程陷入一个系统调用.没有返回的时候会被调度
当m进行系统调用的时候,这个m会被陷入到内核态,毫无疑问的被阻塞了.还是sysmon会定期检测,当一个p上的g执行时间过长
且这个g还是在进行系统调用.那么sysmon会把p与当前m解绑, 然后唤醒一个之前没事做的睡眠的m进行绑定运行.如果没有
睡眠的m就会重新创建一个m来绑定,之前的m运行着进行系统调用的g返回后就会尝试找没有m的p.如果没有找到,m就会把g放到
全局队列,然后自己进入睡眠.

3. 当协程被channel阻塞时会被调度
这个不需要多说.当g被channel阻塞后,这个g会被放到相应的wait队列.该g的状态由_Gruning变成_Gwating,g会被别的g的
channel操作唤醒,那么这个g就会尝试加入那个g所在的p的runnext,如果没有成功,就会加入本地p队列,全局队列.等待被m运行.

4. 当协程进行网络io阻塞的时候会被调度
网络io虽然也算是系统调用,但是go原生的网络包底层全是由epoll类似的驱动的,并不走之前系统调用那一套.sysmon线程会进行
epoll_wait,然后对程序每个socket进行标记,哪些socket是可写的,哪些socket是可读的,然后尝试唤醒因为socket不可写或者
不可读的g,而g在对socket进行读写的时候就判断sysmon有没有对其标记过,如果没有标记过就进入wait状态,如果标记过了就说明可
用就继续操作,操作完了,再把这个标记去除了,等待下次标记.

总结:

1. GMP 三者能够随意绑定解绑,达到了灵活调度的目的
2. go后台运行这sysmon线程来进行调度.和上帝一样.
3. go程序底层有g的对象池,已经对g进行了复用不会被销毁. 同时m也是不会被销毁的.所以从某种意义来讲go确实越运行越占内存.

参考资料

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

推荐阅读更多精彩内容

  • 我是在深入学习 kotlin 时第一次看到协程,作为传统线程模型的进化版,虽说协程这个概念几十年前就有了,但是协程...
    前行的乌龟阅读 99,835评论 32 182
  • 进程时代 后来,现代化的计算机有了操作系统,每个程序都是一个进程,但是操作系统在一段时间只能运行一个进程,直到这个...
    大学渣PG阅读 1,914评论 0 1
  • 如今,微信拥有月活跃用户8亿。 不可否认,当今的微信后台拥有着强大的并发能力。 不过, 正如罗马并非一日建成;微信...
    一凡_44e0阅读 1,023评论 0 0
  • 进程、线程和协程 进程的定义: 进程,是计算机中已运行程序的实体。程序本身只是指令、数据及其组织形式的描述,进程才...
    星丶雲阅读 1,413评论 2 14
  • 阅读1小时,总计552小时,第517日。 阅读《法律的经济分析》至95% 即美国宪法严禁政府在没有正当法律程序的条...
    龙套哥萨克海龙阅读 167评论 0 0