Golang GMP调度模型特性,通过P解耦GM

Golang GMP调度模型特性,通过P解耦GM

Golang轻松学习


一、GMP调度模型是什么?

Golang 由于自己实现的CSP并发模型实现,不依赖操作系统和其提供的线程,所有自己管理控制协程的方式也就是GMP调度模型。

协程

也就是用户态线程,一个“用户态线程”必然要绑定一个内核态线程,但是CPU并不知道有用户态线程的存在,它只知道运行的是一个内核态线程,内核线程依然叫线程(thread),用户线程叫协程(co-routine)。,协程之间的切换发生在用户态线程,也就是协程,在用户态没有时钟中断,系统调用等机制,因此效率高,占用的空间也更少。

二、GMP调度

1.GMP

1.G

G(goroutine):goroutine实体,golang 实现的用户态线程(co-routine),Goroutine的sched保存着其上下文信息。当启动一个 G 时,会优先放入到一个P的本地队列中,P会从线程池里拿一个M(没有则创建)来运行里面的G。

2.M

M(machine):对内核线程的封装,用来运行G,数量等于CPU核数,M需要绑定一个P才能执行里面的G(线程是CPU执行的最小单位),一个P也只能同时绑定一个M去执行里面的G。

如果G阻塞时,执行的M也会阻塞,那么P就会将G留在M,将队列内其他G绑定到另一个可用M继续执行。如果M的G执行完了,找不到其他G,则将G放入到全局队列,M放入空闲线程池里。

3.P

P(processor):调度器,相当于一个调度器,它包含了goroutine运行的资源,。一个P维护着一个G队列,这个本地队列用于存储等待执行的G列表,数量不超过256个,如果队列满了,则新建的G将会被放入到全局队列中。如果队列空了,与之绑定的M会从其他队列或全局队列中拿一部分G过来放到自己本地的队列中,并执行。

可通过GOMAXPROCS()来设置P的数量,默认为核心数,P也会周期性地将全局队列里的G放到自己的本地队列中去执行。

2.调度

将GMP的不同特性整理

  • 程序运行时P创建,默认为核心数
  • 当我们新建 G(goroutine) 时,放入到一个P的本地队列中
  • 如果P的本地队列满了,队列不能超过256个,那么G不能放在P中,那么G将会被放入到全局队列中
  • P会维护着一个G队列,从线程池选择一个M来执行本地队列的G去执行
  • 如果M执行的所有G都不阻塞,那么M会顺序执行
  • 如果存在一个G阻塞,会导致M也解绑,P则会解绑,换一个M继续执行,因为一个P只能与一个M一一对应
  • 当M顺利执行完一部分后,P也会周期性地将全局队列里的G放到自己的本地队列中去执行,直到全局队列中不存在新的G
  • 当M执行完当前P的队列后,P的本地队列为空,那么M就会去其他P的本地队列中获取一半的G,放入自己的P本地队列,继续执行
  • 当G执行完毕,销毁G,所有M放入线程池中,等待下一个G的创建

总结

GMP调度模型设计的核心思想是用较少的线程完成很多Goroutine 的执行,从语言级别支持并发,轻量级协程 Goroutine 。由于P的存在,使得GM,协程也就是用户态线程与内核态线程实现了解耦,当遇到G的阻塞时,不会影响到其他G的使用,P会选择其他M来实现继续执行,提升并发性能。

希望这个博客能对你有所益处。我是轻王,我为自己代言。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猫轻王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值