Go并发调度模型——G-P-M模型

G-P-M模型图解:

在这里插入图片描述
G:G就是goroutine,通过go关键字创建,封装了所要执行的代码逻辑,可以称为是用户线程。属于用户级资源,对OS透明,具备轻量级,可以大量创建,上下文切换成本地等特点

P :Processor即逻辑处理器,默认Go运行时的Processor数量等于CPU数量,也可以通过GOMAXPROCS函数指定P的数量,P的主要作用是管理G运行,每个P拥有一个本地队列并为G在M上的运行提供本地化资源

M:是操作系统创建的系统线程,作用是执行G中包装的并行任务,被称为物理处理器。其属于OS资源,可以创建的数量上也受限与OS,通常情况下G的数量都多于活跃的M。GO运行时调度器将G公平合理的安排到多个M上去执行

G和M的关系:G是要执行的逻辑,M是具体执行G的逻辑,通过P建立G和M的联系从而执行

G和P的关系:P是G的管理者,P将G交由M执行,并管理一定系统资源供G使用,一个P管理存储在其本地队列的所有G。P和G是1:n的关系

P和M的关系:P和M是1:1的关系。P将管理的G交由M具体执行,当遇到阻塞时,P可以与M解绑,并找到空闲的M进行绑定继续执行队列中其他可执行的G。

问题:为什么要有P?
G是对需要执行的代码逻辑的封装,M具体执行G,P存在的意义是什么?

Go语言运行时系统早期(Go1.0)的实现中并没有P的概念,Go中的调度器直接将G分配到合适的M上运行。但这样带来了很多问题,例如,不同的G在不同的M上并发运行时可能都需向系统申请资源(如堆内存),由于资源是全局的,将会由于资源竞争造成很多系统性能损耗。
Go 1.1起运行时系统加入了P,让P去管理G对象,M要想运行G必须先与一个P绑定,然后才能运行该P管理的G。P对象中预先申请一些系统资源作为本地资源,G需要的时候先向自己的P申请(无需锁保护),如果不够用或没有,再向全局申请。而且从全局拿的时候会多拿一部分,以供后面高效的使用。
P的存在解耦了G和M,当M执行的G被阻塞时,P可以绑定到其他M上继续执行其管理的G,提升并发性能。

GO的调度过程:

①创建一个goroutine,调度器会将其放入全局队列。
②调度器为每个goroutine分配一个逻辑处理器。并放到逻辑处理器的本地队列中。
③本地队列中的goroutine会一直等待直到被逻辑处理器运行。

func task1() {
    go task2()
    go task3()
}

假设现在task1在称为G1的goroutine中运行,并在运行过程中创建两个新的goroutine,新创建的两个goroutine将会被放到全局队列中,调度器会再将他们分配给合适的P。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值