深入探讨Go语言协程调度:GRM模型解析与优化策略

一、线程调度

1、早期单线程操作系统
  • 一切的软件都是跑在操作系统上,真正用来干活(计算)的是 CPU
  • 早期的操作系统每个程序就是一个进程,直到一个程序运行完,才能进行下一个进程,就是“单进程时代”
  • 一切的程序只能串行发生

2、多进程/线程时代 
  • 在多进程/多线程的操作系统中,就能解决了阻塞的问题,因为一个进程阻塞 cpu 可以立刻切换到其他进程中去执行
  • 而且调度 cpu 的算法可以保证在运行的进程都可以被分配到 cpu 的运行时间片
  • 这样从宏观来看,似乎多个进程是在同时被运行
  • 但新的问题就又出现了,进行拥有太多的资源,进程的创建、切换、销毁、都会占用很长的时间
  • CPU 虽然利用起来了,但如果进程过多,CPU 有很大的一部分都被用来进行进程调度了
  • 大量的进程/线程都出现了新的问题
    • 高内存占用
    • 调度的高消耗 CPU
    • 进程虚拟内存会占用 4GB[32位操作系统],而线程也要大约 4MB

3、Go 协程 goroutine 
  • Go 中,协程被称为 goroutine,它非常轻量,一个 goroutine 只占几 KB,并且这几 KB 就足够 goroutine 运行完
  • 这就能在有限的内存空间内支持大量 goroutine;支持了更多的并发
  • 虽然一个 goroutine 的栈只占几 KB,但实际是可伸缩的,如果需要更多内容,runtime 会自动为 goroutine 分配
  • Goroutine 特点:
    • 占用内存更小(几 KB)
    • 调度更灵活(runtime 调度)
4、协程域线程区别
  • 协程跟线程是有区别的,线程由 CPU 调度是抢占式的
  • 协程由用户调度是协作式的,一个协程让出 cpu 后,才执行下一个协程

二、调度器 GMP 模型

  • G:goroutine(协程)
  • M:thread(内核线程,不是用户态线程)
  • P:processer(调度器) 
1、GM 模型
  • G(协程)通常在代码里用 go 关键字执行一个方法,那么就等于起了一个 G
  • M(内核线程)操作系统内核其实看不见 G 和 P,只知道自己在执行一个线程
  • G 和 P 都是在用户层上的实现
  • 并发量小的时候还好,当并发量大了,这把大锁,就成了性能瓶颈

  • GMP 由来
    • 基于没有什么是加一个中间层不能解决的思路,golang在原有的GM的基础上加入了一个调度器P
    • 可以简单理解为是在G和M中间加了个中间层
    • 于是就有了现在的GMP模型里的P
2、GMP模型

三、GMP流程分析 

  • 我们通过go func()来创建一个goroutine
1、P本地队列获取G
  • M想要运行G,就要先获取P,然后从P的本地队列获取G

2、本地队列中G移动到全局队列
  •  新建G时,新G会优先加入到P的本地队列
  • 如果本地队列满了,则会把本地队列中一半的G移动到全局队列

3、从其他P本地队列的G放到自己P队列
  •  如果全局队列为空时,M会从其他P的本地队列偷(stealing)一半G放到自己P的本地队列

4、M从P获取下一个G,不断重复
  • M运行G,G执行之后,M会从P获取下一个G,不断重复下去

相关推荐

  1. GO语言调度原理和使用方法

    2023-12-09 20:44:02       40 阅读
  2. 深入探索 MongoDB:高级索引解析优化策略

    2023-12-09 20:44:02       26 阅读
  3. Go语言使用

    2023-12-09 20:44:02       59 阅读
  4. Sylar---调度模块

    2023-12-09 20:44:02       28 阅读
  5. go语言GMP模式介绍以及案例展示

    2023-12-09 20:44:02       50 阅读
  6. 深入解析:MySQL连接超时问题排查优化策略

    2023-12-09 20:44:02       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-09 20:44:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-09 20:44:02       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-09 20:44:02       82 阅读
  4. Python语言-面向对象

    2023-12-09 20:44:02       91 阅读

热门阅读

  1. 学会用bash在linux写脚本 (二)

    2023-12-09 20:44:02       58 阅读
  2. python如何在多线程中使用异步

    2023-12-09 20:44:02       56 阅读
  3. ssh隧道转发

    2023-12-09 20:44:02       61 阅读
  4. 使用c#罗列、监视、控制进程

    2023-12-09 20:44:02       55 阅读
  5. Pytorch中的resize和reshape

    2023-12-09 20:44:02       54 阅读
  6. [原创] FPGA的JTAG烧录不稳定或烧录失败原因分析

    2023-12-09 20:44:02       66 阅读
  7. CCF-走迷宫(bfs)

    2023-12-09 20:44:02       57 阅读