GMP分析(一)

本文详细介绍了Golang中的GMP模型,包括协程(g)、线程(m)和处理器(p)的概念。GMP模型旨在优化线程管理和调度,减少上下文切换的开销。Golang通过引入p,使得每个处理器p拥有自己的g队列,提高了调度效率。当协程阻塞时,runtime会将m重新关联到其他可用的p或创建新线程。文章还阐述了G0和M0的作用,以及GOMAXPROCS对处理器队列的影响。
摘要由CSDN通过智能技术生成

GMP g指的是协程、m指的是线程、p指的是处理器

调度:指的是调度cpu,在多线程、多进程的场景,保证每个线程、进程看上去都在执行。

进程、线程的创建、销毁都比较占用cpu的调度时间,而且线程的调度还要考虑到多线程之间资源的竞争、锁的问题等。

用户态线程指的是程序里面用户创建的线程,内核态线程指的是cpu调用的线程。

这个时候就引入了协程的概念,可以在用户态的线程来管理协程,这样就减少了内核态线程调用用户态线程的切换。

golang中协程的调用都是在用户态的线程中进行实现的。如果一个协程阻塞,这个线程中的其他协程会被runtime转移到其他可以用的线程中,或者创建新的线程。(这个也是造成golang进程中,线程数量过大的原因)。

golang初始的gm版本(已废弃)没有p,调用还是依靠的cpu:

1. g有一个全局的g队列,每一个m获取g时,都需要加锁进行互获取。

2. 在m中如果有新创建的协程g1时,最好是g1在m中执行,这种关联是不合理的。或者在m1上执行也是不合适的。

3. golang在多线程之间的切换导致线程的阻塞与取消阻塞也增加了系统的开销。

最新版本的gmp:

引入了最新的处理器p,每个p中包含了可以运行的g队列。m想运行g,必须先获取p。

重点:

  1. 全局队列,用来存储需要运行的g列表
  2. p本地队列,本地队列存储的也是可以运行的g队列,但是总量不会超过256个,如果在m中创建新的g,会把新创建的g放到p的本地队列中。如果队列满了,会把本地队列的一半放入到全局队列中。
  3. p列表,所有的p都会在程序启动时创建,最多有GOMAXPROCS个p。
  4. m运行g,会从p的本地队列中进行获取,如果本地队列为空,会从全局队列G中获取一部分g队列,或者从其他的p本地队列中偷取一部分过来。

整体逻辑:

在进程启动后,会根据GOMAXPROCS创建需要的处理器队列

m在获取需要运行的g时,会首先获取一个未被关联的p,如果未获取到则m休眠。在获取到p后,会先从p的本地g队列中获取可运行的g,如果本地g队列中没有可运行的g,会优先从其他p中偷取一部分g,如果未获取到,则会从全局队列中获取一部分可运行的g。整个执行过程是一个循环的过程。

m如果在调用过程中,出现阻塞,则runtime会把m从当前的p中摘除,重新关联一个空闲的线程或者重新创建一个线程。

m是复用线程的,如果当前线程关联的p没有可运行的g,不会销毁线程,会从其他p或者全局队列获取可运行g。

G0指的是每个M启动时,创建的第一个协程,仅用来负责G的调度。

M0时程序启动时创建的第一个线程,用来启动第一个G。这个M0对应的实例会在全局变量runtime中,其他新创建的M会放在heap上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

it程序员-郭泽

多少都是心意,谢谢大家

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

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

打赏作者

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

抵扣说明:

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

余额充值