golang协程调度面试总结

1.go的GMP模型

goroutine运行在用户态,是由runtime来控制调度的,调度过程中主要涉及到三个对象:G-go关键字启动的协程(也有内部启动的协程如g0)、M-运行G的系统线程(由操作系统控制调度)、P-资源处理器,用来管理G的,M必须绑定一个P才能运行其协程队列里的G。具体的调度过程是这样的:
程序启动时创建GOMAXPROCS个P,当有go关键字创建G时会优先加入到当前P的本地队列中(缓存局部性原理),当本地队列满了调度器会调度部分协程到全局队列中,此时P去线程池唤醒一个休眠的M(如没有则新创建一个M)进行绑定,M获取到P本地队列中的G开始执行,当本地队列里面的G执行完则先去全局队列获取,若获取不到则去其它队列偷取,若都没有则当前M进入自旋状态(因为线程的创建销毁唤醒比较消耗CPU,但是自旋线程本质是线程在运行不过没有执行G,因此也有数量限制,超过限制M休眠),不断的循环寻找等待新的G。

2.怎么防止G全局队列饥饿

极端情况下所有本地队列的G被执行数和生产新的G数量保持“平衡”,导致全局队列里的G饥饿无法被执行。go调度器为了公平起见,每执行61次G后会直接去全局队列取1个G。

//go1.18.4/src/runtime/proc.go:3175
// Check the global runnable queue once in a while to ensure fairness.
// Otherwise two goroutines can completely occupy the local runqueue
// by constantly respawning each other.
if _g_.m.p.ptr().schedtick%61 == 0 && sched.runqsize > 0 {
    lock(&sched.lock)
    gp = globrunqget(_g_.m.p.ptr(), 1)
    unlock(&sched.lock)
}

3.G、M、P的个数

  • golang创建协程内存消耗较小(2K左右,理论上个数受内存大小限制),加上G在退出时会把G清理掉后放入本地或者全局空闲列表的gfree队列中以方便复用,配置一般的机器也能开启十万级 goroutine。
  • M线程的个数默认是10000个,线程相较G耗资源,一般达不到该数量,M必须绑定一个P才能执行G,所以M的数量一般大于等于P的数量。
  • P的个数由GOMAXPROCS控制,默认为CPU的核数。

4.go的协程调度策略,具体如何抢占的

进程由操作系统调度,分为抢占式调度和非抢占式调度(FCFS),抢占式调度有先到先得(FIFO)、最短任务优先(SJF)、最短完成时间任务优先(STCF)、时间片轮转(Round-Robin, RR)等策略。操作系统调度策略
协程由runtime在用户态进行调度的,采用时间片算法的方式,公平,可以防止少数协程长时间执行导致其它协程饥饿。
具体的抢占过程是基于信号的方式:程序运行时守护线程sysmon会去监控执行所有G的时间,如果G超过了10ms,sysmon会给当前的M发送一个sigurg信号,M中断执行该G(放入全局队列),去获取新的G;当调用syscall时间太长时也会发送sigurg信号。

5.GMP模型,发生了阻塞怎么办,如何保证G不会被其他G的系统调用、网络调用阻塞

  • M系统线程发生系统调用阻塞
    1.如G打开文件时,M与P解绑并阻塞进入等待状态,G也进入等待状态,此时P唤醒一个M或者创建一个新M继续执行后面的G;
    2.当系统调用结束,M优先和旧P进行绑定继续执行G(亲和性、局部性);如果旧P正在被使用并且有空闲的P,则新P和M绑定,刚才阻塞的G加入其本地队列,M继续执行G;如果没有空闲的P,G加入到全局队列中,等待被其它的P调度,然后M将进入缓存池休眠。
  • G协程阻塞
    1.G读写channel时阻塞:此时MP不解绑(M继续执行后面的G),而G加入到channel的recvq或sendq队列中进行等待,当有数据写channel或有读channel时唤醒对应的G,加入P的本地队列或者全局队列等待执行。
    2.G发起网络请求时阻塞:比如当创建完一个Listener,调用Accept开始接收客户端连接。如果没有对应的请求,那么最终会把G放入到pollDesc的rg;
    如果是一个conn类型的fd等待可写I/O,那么会把G放入到pollDesc的wg中。rg、wg都是指针类型,实际这两个字段存储的就是Go底层的G,更具体点是等待i/O ready的G。

6.协程的状态

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

推荐阅读更多精彩内容