golang 线程模型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kkx12138/article/details/82226913

1. 基本概念

M: 内核线程
P: go 代码片段所必须的上下文环境
G: go 代码片段
调度器: 管理和调度 M, P, G

2. 存储容器

全局M 列表: 存储所有M的一个单向链表
全局P 列表: 存储所有P的一个数组
全局G 列表: 存储所有G的一个切片
调度器的空闲M列表: 存放空闲M的单向链表
调度器的空闲P列表: 存放空闲P的单向链表
调度器的可运行G列表: 存放可运行的G的一个队列
调度器的自由G列表: 存放自由的G的两个单向链表
P的可运行G队列: 存放当前P的可运行G的一个队列
P的自由G列表: 存放当前P的自由G的一个单向链表

3. M, P, G联系

一个go程序会有一个调度器, 这个调度器会管理和调度 多个M,P,G。
P 在M上运行,一个P与一个M结合, 但是P也会在多个M间迁移。
G 需要与P结合才能在M上运行。 一个P会对应多个G(G列表), G本身也会在多个P间迁移。

4. 如何运行

4.1 G

当我们用go关键字调用go函数的时候, 调度器会尝试从当前M关联的P的自由G列表中获取G,如果P的自由G列表为空, 则从调度器的自由G列表中分一些给P, 如果调度器的自由G列表也为空, 就创建一个G, 至此就封装成了G。 G 会进入到可运行状态,加入到可运行G队列。 我们看到有两个可运行G队列, 一个是P的, 一个是调度器的,其实两个中的G是由不同状态转化而来的, 具有平等的运行机会。 之后G便等待P的执行通知。

4.2 P

运行时系统会有一个调度器的空闲P列表,当一个P不在与任何一个M关联的时候(只有当P的G列表为空的时候), 运行时系统就会把它加入到该列表; 当系统需要一个空闲的P关联某个M的话, 会从这个列表中取出一个。 这样P就关联了一个M, 也只有这样P中的可运行G队列才有可能运行。

4.3 M

运行时系统会一个调度器的空闲M列表, 当执行垃圾回收等任务的时候, 会将一个M加入到其中。 当需要使用的时候就从里面获取一个。 如果没有足够多的M来关联P, 就会创建一个M。

ref :
【1】Go并发编程实战 郝林

猜你喜欢

转载自blog.csdn.net/kkx12138/article/details/82226913