前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >go-GMP原理

go-GMP原理

原创
作者头像
用户9879380
修改2025-03-21 15:38:14
修改2025-03-21 15:38:14
640
举报

概念

  • 进程是操作系统资源分配的基本单位,比如cpu时间,内存
  • 协程是用户态线程,由用户通过go func命令创建
  • 线程是内核态线程,由cpu调度,由go的runtime创建

GPM

定义

  • P go的proc,处理器,非cpu
  • G 协程,一般放在P本地队列中执行
  • M内核态线程,处理 P里面的G
  • P的本地队列,本地队列里包含未处理的G
  • P的全局队列,进程启动时会将创建好的P全部放入
  • G全局队列,大多储存因G阻塞后不再阻塞,但没有空闲的P处理的G
  • M空闲队列:存储因找不到 P而没有可处理G的线程
  • G空闲池:将处理完的G放入空闲池中,下次创建协程时可直接取出,避免了内存GC
  • G0: 专门负责调用P中的G,且也处理M和P解绑等问题,类似于管理员

执行原理

进程启动时执行逻辑

  • 创建主线程M0,也创建协程G0
  • 根据GoMaxProc的设置,创建对应数量的P并放入P全局队列中
  • 此时用户创建协程,则将G放入本地队列P中,P寻找空闲M0开始执行调度
  • 若此时P本地队列已满,则取出P队列的一半放入G全局队列,再将当前G放入P的本地队列
  • G被调度后,若发生阻塞,则P会和M解绑,寻找新的空闲的M1,先从M的空闲队列中寻找,若无,则runtime创建新的M1,对P和M1进行绑定,继续执行P中剩余G
  • 阻塞的G处理完成后,M会寻找空闲的P将G放入并进行调度,若无空闲P, 则将G放入G的全局队列,M放入M空闲队列
  • P本地队列会定时查看G全部队列的G,P中有空闲则会将拿一部分G放入P中处理,若本地队列无需要处理的G,则取其他的P1,P2中查看是否有多的,未处理的G,有则取出一般来放入P中,让P进行处理

已有协程上创建协程

  • G创建G1,则优先将G1放入G所在本地队列,避免切换处理器带来跨P通信的开销
  • 若此时P本地队列已满,则将队列中一半协程放入G全局队列,再将G1放入P本地队列中
  • 若此时P队列未满,则直接放入
  • 调度时,优先调度P队列中的协程
  • P队列为空,则先去G全局队列中找,有则取协程放入P队列,若无,则取其他的P队列查看是否有多余未处理的G

关键点

  • 线程、协程的复用,避免的内存GC以及线程和协程的创建和销毁带来的性能损耗
  • P本地队列的Hand off策略,让协程可以更加快速被调度
  • 抢占,每个协程可使用的cpu的时间都是固定的,避免cpu始终被个别协程独占

注意

  • 图片参考深入理解Go语言一书

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念
  • GPM
    • 定义
    • 执行原理
      • 进程启动时执行逻辑
      • 已有协程上创建协程
    • 关键点
      • 注意
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档