goroutine 基本模型和调度器策略详解

本文介绍了操作系统从单线程到多线程的发展,探讨了多线程带来的问题,如线程切换成本和内存消耗,并详细阐述了Go语言中的协程(Goroutine)模型,特别是GMP模型,如何通过轻量级的协程和智能调度解决这些问题。同时,还解析了Go调度器的四种策略,包括线程复用、工作窃取和抢占等机制,以实现高效的任务执行和资源利用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里将简单阐述多线程的故事,协程的故事,和 go goroutine 的故事

(1)原始的单线程操作系统

同时只能执行一个线程,简单的单线程
问题:

  • 单一执行,计算机智能一个一个处理
  • 进程阻塞浪费:如果一个进程阻塞了,整个系统就阻塞了
  • CPU浪费:CPU 只是在计算的时候会用到,比如程序的 IO ,CPU 利用率低下,大部分时间都是空闲的
  • 现在几乎没有这种单线程的模式了
    在这里插入图片描述
(2) 常见多线程操作系统

单线程的问题,我们用多线程的解决方案来解决
操作系统的多线程将线程用时间来切片(比如每个线程执行 5ms 然后切换到下一个线程,然后重宏观角度上来看,就是很多应用并发执行的)
在这里插入图片描述

解决了 阻塞和CPU利用率低下的问题
但是

产生问题:

  • 线程切换成本:切换需要CPU调用系统调用,资源的拷贝复制,都会浪费很多时间,而且线程越多,越浪费时间
  • 内存消耗:进程占用的内存(32位)最多是 4G,线程大约占用 4M 左右,线程越多,越是浪费内存
  • 开发困难:多线程就必须要解决变量统一问题(锁)和资源竞争问题,开发变得越来越困难

在这里插入图片描述

(3)go 协程模型 GMP 模型

解释 GMP 模型

  • 蓝色的 M 都是内核线程,线程是操作系统调度的最小单位,协程是 P 调度器调度的
  • 黄色的 P 就是 Processor 调度器,用来调度协程给线程运行
  • 绿色的 G 是 go协程 goroutine,负责运行具体的协程代码,就是你写的代码就在这上面运行
  • P的本地队列,是 P 调度器负责调度的协程存放的队列,对列里面的协程是抢占式执行(比如一个协程执行 5ms 就换到下一个协程)
  • 全局队列是「等待队列」:当所有的 P 本地协程队列都满了之后,放不下的都放到全局队列里面,全局队列是加锁的

多加一层 P:
多加一层的概念在计算机里面十分常见,比如 JDBC 就是为了统一数据库连接,比如 MVC 三层架构…多加一层是十分常见的
这里面就是用了多加一层的手法多加了一层 P 调度器

轻便
goroutine 只有 几KB 是十分轻便的

不用大量切换线程浪费资源

协程本地队列,中协程的切换而不是线程的切换,让操作系统的线程最大程度的处于计算状态

在这里插入图片描述

(4)go 调度器的 4 种策略,解决阻塞并让线程最大程度的计算

1.复用线程
复用线程有 2 个机制

  • 1.1 work stealing 偷取:如果一个 P 上的 G协程 队列为空,他会优先偷取其他 P 上的 G 协程队列,其他都为空,才会去全局队列中去拿
  • 1.2 hand off 切换:如果有一个协程阻塞了,并且所有的其他队列都在有,没有必要去偷取

1.1 work stealing 偷取机制
在这里插入图片描述

1.2 hand off 切换机制

如果正在运行的协程 G1 阻塞了,但是其他的调度器都在处理自己的业务,没有时间去偷 work stealing 这阻塞的 G1 上面队列中的其他协程
我们就:唤醒一个线程,或者开启一个线程,将我们之前的在调度器和其他没有阻塞的协程切换过去
在这里插入图片描述

在这里插入图片描述
G 阻塞接受后,如果还要运行,就放到其他调度器 P 上面的协程队列中,如果不执行,就将 M1 线程休眠或销毁即可

2. 利用并行
利用 GOMAXPROCES 最大 P的数量限定,P的个数比如 CPU数/2

抢占
M -> P ->Gs队列,G队列中是一个抢占策略,如果超过时间还没有执行完,就切换其他线程执行,就像是 多线程操作系统的模型

全局队列

  • 将 P 中的本地队列放满了,才会放到全局队列,
  • 只有 steal 偷取策略偷不到了,才回去,全局队列去拿,全局队列是加锁的

参考视频教程
https://www.bilibili.com/video/BV1gf4y1r79E?p=26

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JarvanStack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值