golang GMP模型

学习教程, 看11分钟

image-20211101223546242

一个进程 可以有多个线程 ,每个线程 有多个协程

协程和线程的关系

image-20211101224217883

N:M原理

image-20211101224258195

一个协程可以挂到不同的线程上面去,所以是 N:M

每个协程可以被不同的线程去执行调度,所以 一个协程 可以属于N个线程, 一个线程 也可以调度 M 个协程,所以是 N:M 关系

一个协程 内存只是占用几个 kb, 一个线程 java里面 占用 1MB ,

使用协程的话,砍掉了很多不必要的内存空间,调度更加灵活了。

调度器策略

image-20211101234721219

可视化 GMP编程

通过 go tool trace 工具可以打开 trace 文件

工作窃取算法

image-20211102104906465

整个流程就是 M 线程 如果空闲,先去其他的 线程的 任务队列里面偷任务来执行【工作窃取算法】, 如果偷不到其他的队列的任务,再从全局队列中取出 groutine 来执行。

因为 如果都从全局队列中拿,会占用锁,所以从其他线程的本地队列中 获取 会比较好。

大致流程

GMP调度流程大致如下:

  • 线程M想运行任务就需得获取 P,即与P关联。
  • 然而 P 的本地队列(LRQ)获取 G
  • 若LRQ中没有可运行的G,M 会尝试从全局队列(GRQ)拿一批G放到P的本地队列,
  • 若全局队列也未找到可运行的G时候,M会随机从其他 P 的本地队列偷一半放到自己 P 的本地队列。
  • 拿到可运行的G之后,M 运行 G,G 执行之后,M 会从 P 获取下一个 G,不断重复下去。

https://img-blog.csdnimg.cn/img_convert/0740098bdb9889fbbf2556005834ac55.png