前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GMP模型面试问题

GMP模型面试问题

作者头像
孟斯特
发布2024-06-11 18:55:33
630
发布2024-06-11 18:55:33
举报
文章被收录于专栏:code人生code人生

GMP模型概述

GMP模型是Go语言的并发调度模型,它是由Goroutine、M(OS线程)和P(处理器)三个主要组件构成的。这个模型是Go运行时(runtime)用来调度Goroutines执行的机制,它允许数以万计的Goroutines能够在有限数量的线程上高效运行。下面是GMP模型各个组件的详细说明:

Goroutine(G)

Goroutine是Go语言中的轻量级线程,它是并发执行的实体。与OS线程相比,Goroutines的创建和销毁成本要低得多,它们占用的内存也更少,通常只有几KB。Goroutines在逻辑上是独立的,但实际上是由M来执行的。

M(Machine或OS线程)

M代表Machine,实际上就是操作系统的线程。Go运行时会在物理或虚拟处理器上创建一定数量的线程,这些线程用于执行Goroutines。每个M都会绑定一个P,然后从P的本地运行队列中获取Goroutine来执行。如果M阻塞了(例如,等待I/O操作),它会释放P,然后运行时会创建或唤醒另一个M来绑定到P上,以保持CPU的利用率。

P(Processor或处理器)

P代表Processor,它是Goroutine执行所需的资源的抽象。P的数量通常由GOMAXPROCS环境变量控制,它决定了系统同时可以有多少个Goroutines在运行。每个P都有一个本地的Goroutine队列,它负责维护等待运行的Goroutines。P的作用是将Goroutines分配给M来执行,它是M和G之间的调度器。

GMP模型的工作原理

1.初始化:程序启动时,Go运行时会根据GOMAXPROCS的值创建相应数量的P,并创建一些M来服务这些P。2.执行Goroutines:每个P会从其本地队列中取出一个Goroutine,并将其分配给一个M来执行。3.全局队列和本地队列:如果一个P的本地队列为空,它会尝试从全局队列中获取Goroutines,或者从其他P的本地队列中“偷取”一半的Goroutines。4.阻塞和唤醒:如果一个M在执行Goroutine时被阻塞,它会释放P,并进入休眠状态。运行时会创建或唤醒另一个M来接管P。当阻塞的M完成等待的操作后,它会尝试获取一个空闲的P来继续执行Goroutines;如果没有空闲的P,它会将Goroutine放入全局队列,并进入休眠状态。

M与P

绑定时机

在Go语言的GMP模型中,M(Machine)与P(Processor)的绑定是由Go运行时进行管理的。绑定过程是在M需要执行Goroutines时发生的。以下是M与P绑定的一般过程:

1.启动时绑定:当Go程序启动时,Go运行时会根据GOMAXPROCS的值创建相应数量的P。同时,运行时也会创建一些M来服务这些P。每个M在启动时会尝试获取一个P,如果获取成功,M就与这个P绑定。2.执行Goroutines:一旦M与P绑定,M就可以从P的本地运行队列中取出Goroutines来执行。如果本地队列为空,M(通过P)可以尝试从全局队列获取Goroutines,或者从其他P的本地队列中“偷取”Goroutines。3.阻塞和解绑:如果M在执行Goroutine时被阻塞(例如,等待系统调用),它会释放P,这样其他的M就可以使用这个P来执行Goroutines。释放P的过程实际上是M与P的解绑。4.唤醒和重新绑定:当M完成阻塞操作并被唤醒时,它会尝试重新获取一个P。如果有空闲的P,M将与之绑定并继续执行Goroutines。如果没有空闲的P,M可能会将其Goroutine放入全局队列,并进入休眠状态,直到有可用的P。5.工作窃取:为了保持所有的M都在工作,Go运行时会使用工作窃取算法来平衡不同P的负载。如果一个M通过其绑定的P无法找到可执行的Goroutine,它会尝试从其他P的本地队列中窃取Goroutine来执行。6.调度器介入:Go运行时的调度器会监控所有的M、P和Goroutines,确保每个M都有工作可做。调度器会在必要时介入,进行M与P的绑定和解绑,以及Goroutines的分配。

通过这种动态绑定和解绑的机制,Go运行时能够有效地利用系统资源,同时保持高并发性能。这种设计允许Go程序在多核处理器上实现高效的并发执行,而不需要程序员进行复杂的并发管理。

对应关系

在Go语言的GMP模型中,M(Machine,操作系统线程)和P(Processor,处理器)之间的对应关系是动态的,而不是一对一的固定关系。这种设计允许Go运行时(runtime)更灵活地调度Goroutines(G),以实现高效的并发执行。下面是M和P之间对应关系的几个关键点:

动态绑定

绑定:一个M在执行Goroutines之前,需要绑定一个P。绑定发生在M准备执行Goroutine时,M会从系统的P池中获取一个可用的P并与之绑定。这个过程是动态的,意味着M可以在不同时间绑定不同的P。•解绑:当M因为某些原因(如系统调用阻塞)不能继续执行Goroutines时,它会释放或解绑当前的P,使得其他的M可以绑定该P并继续执行Goroutines。当M再次准备执行Goroutines时,它需要重新绑定一个P。

多对多关系

多个M可以共享P池:系统中的所有M共享一个P池。这意味着多个M可能在不同时间绑定同一个P(当然,不是同时绑定)。•一个M在任何时刻只能绑定一个P:虽然M可以在其生命周期内绑定多个不同的P,但在任何给定的时刻,一个M只能绑定一个P。•一个P在任何时刻只能被一个M绑定:同样,虽然一个P可以在其生命周期内被多个不同的M绑定,但在任何给定的时刻,一个P只能被一个M绑定。

调度和负载平衡

工作窃取:为了保持所有的M都在工作,Go运行时使用工作窃取算法来平衡不同P的负载。如果一个M通过其绑定的P无法找到可执行的Goroutine,它会尝试从其他P的本地队列中窃取Goroutine来执行。•全局队列和本地队列:P拥有本地队列,用于存储准备执行的Goroutines。当P的本地队列为空时,M可以从全局队列获取Goroutines,或者从其他P的本地队列中窃取Goroutines。

M与G

在Go语言的GMP(Goroutine, Machine, Processor)模型中,M(Machine)与G(Goroutine)的对应关系是多对多的。这意味着一个M可以在其生命周期内执行多个G,而一个G也可以在其生命周期内被多个M执行。这种关系是由Go运行时的调度器动态管理的。以下是M与G之间对应关系的几个关键点:

1.多个Goroutines:一个M可以执行多个Goroutines,但在任何给定的时刻,它只能执行一个Goroutine。当一个Goroutine执行完毕、阻塞或者主动让出执行权时,M会从与之绑定的P的本地队列或全局队列中选择另一个Goroutine来执行。2.上下文切换:当一个Goroutine因为I/O操作、系统调用或者其他阻塞操作而不能继续执行时,M会进行上下文切换,挂起当前的Goroutine,并选择另一个Goroutine继续执行。这个过程是由Go运行时的调度器控制的。3.工作窃取:如果M的当前P的本地队列中没有可运行的Goroutine,M可以尝试从其他P的本地队列中“偷取”Goroutine来执行。这是Go运行时为了保持所有M都在工作而采用的一种策略。4.Goroutine的状态:Goroutines在它们的生命周期中会有不同的状态,如_runnable_(可运行的)、_running_(正在运行的)、_waiting_(等待的)、_dead_(结束的)。一个Goroutine可能会在多个M之间迁移,这取决于它的状态和系统的调度策略。5.Goroutine的调度:Go运行时的调度器使用了一个称为M:N调度的模型,其中M代表操作系统线程,N代表Goroutines。调度器会根据系统的负载和资源情况,动态地将Goroutines分配给M来执行。6.并发执行:尽管一个M在任何时刻只能执行一个Goroutine,但由于Go程序通常会有多个M(操作系统线程)同时运行,因此多个Goroutine可以并发执行。

总结来说,M与G的对应关系是由Go运行时的调度器动态管理的,一个M可以执行多个Goroutines,但在任何给定的时刻只能执行一个Goroutine。这种多对多的关系使得Go能够高效地处理并发任务,同时最大化地利用多核处理器的能力。

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)[1]进行许可,使用时请注明出处。 Author: mengbin[2] blog: mengbin[3] Github: mengbin92[4] cnblogs: 恋水无意[5] 腾讯云开发者社区:孟斯特[6]

References

[1] 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0): https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh [2] mengbin: mengbin1992@outlook.com [3] mengbin: https://mengbin.top [4] mengbin92: https://mengbin92.github.io/ [5] 恋水无意: https://www.cnblogs.com/lianshuiwuyi/ [6] 孟斯特: https://cloud.tencent.com/developer/user/6649301

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟斯特 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • GMP模型概述
    • Goroutine(G)
      • M(Machine或OS线程)
        • P(Processor或处理器)
          • GMP模型的工作原理
          • M与P
            • 绑定时机
              • 对应关系
                • 动态绑定
                • 多对多关系
                • 调度和负载平衡
            • M与G
              • References
              相关产品与服务
              云开发 CloudBase
              云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档