Go高阶 の 协程调度器原理



一. Golang协程调度器得由来

1.1多线程和多进程带来的弊端

在这里插入图片描述

在这里插入图片描述
以单核操作系统为例,根据时间片轮转机制,不同的线程就要不断的切换,那么 线程的数量越多,切换成本也就越大,也就越浪费,同样,多线程随着同步竞争(如锁、竞争资源冲突等),让开发变得越来越复杂

而且进程和线程占用内存比较大

  • 进程占用内存 虚拟内存 4GB
  • 线程占用内存 越 4MB

所有面临的两个问题,就是 CPU 的高消耗,和 内存的 高 占用。
在这里插入图片描述



1.2 Go 怎么做的?

正常的一个线程,是分为用户空间和内核空间的。

在这里插入图片描述
我们可以直接把线程的上下两个部分给直接拆开
在这里插入图片描述
给他们起个别名,上边的就叫协程,通过协程调度器进行控制协程的切换
在这里插入图片描述
在这里插入图片描述




二. Goroutine调度器的GMP模型设计思想

GMP 解释

  • G:goroutine 协程
  • P:processor 处理器
  • M:thread 内核线程

在这里插入图片描述

  1. 全局队列:存放等待运行的 G

  2. P的本地队列

    • 存放等待运行的 G
    • 数量限制:不超过 256 G
    • 优先将新建的 G 放在 P 的本地队列中,如果满了就会放到全局队列中
  3. P列表

    • 程序启动时创建
    • 最多有 runtime.GOMAXPROCS() 个,可以配置
  4. M列表 : 当前操作系统分配到 Go 程序的内核线程数,他不是动态可变的。

    • m的数量go语言本身限制是 10000 个
    • 有一个阻塞,就会创建一个新的 M
    • 如果有 M 空闲,那么就会回收或者睡眠



调度器的设计策略

  • 复用线程
    • work stealing 机制
    • hand off 机制
  • 利用并行
    • GOMAXPROCS 限定 P 的个数
    • CPU核数/2
  • 抢占: 抢占可以理解为,每个CPU 最多分配10ms的时间,每个 goroutine 的优先级都是一样的。
  • 全局 G 队列:当其他的队列取不到的时候,就从全局队列里取一个,一般情况下,刚加入的 GO 会加入到本地队列里,而不会加入到全局队列中。

偷取工作:

当本线程无可用的 G 时,尝试从其他线程捆绑的 P 偷取 G,而不是销毁线程。
在这里插入图片描述

hand off 传球
当本线程因为 G 进行系统调用阻塞时,线程释放捆绑的 P,把 P 转移给其他空闲的线程执行。
在这里插入图片描述
在这里插入图片描述




调度器得生命周期

在这里插入图片描述




参考文献

[1]https://www.bilibili.com/video/BV19r4y1w7Nx?p=11&share_source=copy_web

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值