当前位置: 首页 > news >正文

golang面经——GMP相关

1.什么是 GMP?(必问)调度过程是什么样的?(对流程熟悉,要求更高,问的较少)

1.1 什么是GMP?

        GMP 是一个核心的并发模型,它代表 Goroutine(协程)、M(Machine,线程)和 P(Processor,处理器)。GMP 是 Go 运行时(runtime)用来高效管理和调度并发任务的关键机制。

1)G(Goroutine)
定义:Goroutine 是 Go 语言中的轻量级线程,由 Go 运行时管理。与操作系统线程相比,Goroutine 的创建和销毁开销极小(初始栈大小约 2KB),可以轻松创建成千上万个并发任务。
特点:
通过 go 关键字启动(例如 go func())。
依赖 GMP 模型调度,而非直接绑定操作系统线程。

2) M(Machine)
定义:M 是操作系统线程(OS Thread)的抽象,由操作系统直接管理。每个 M 负责执行 Goroutine 的代码。
特点:
M 的数量默认有限(通常与 CPU 核心数相关,可通过 GOMAXPROCS 调整)。
M 必须绑定一个 P 才能执行 G。

3) P(Processor)
定义:P 是逻辑处理器,是 G 和 M 之间的中间调度层。P 的数量默认等于 CPU 核心数(可通过 GOMAXPROCS 设置)。
作用:
P 维护一个本地 Goroutine 队列(local queue),避免全局队列的锁竞争。
P 负责将 G 分配给 M 执行。

GMP 的工作流程
创建 Goroutine:当调用 go func() 时,会创建一个 G,优先放入当前 P 的本地队列。当这个p队列满了的时候,本地队列满了时会将本地队列的一半 G 和新创建的 G 一起放入全局队列。
M 获取 G: M 优先执行其所绑定的P的本地运行队列中的 G,如果本地队列没有 G,则会从全局队列获取为了提高效率和负载均衡,会从全局队列获取多个 G,而不是只取一个,同样,当全局队列没有时,会从其他 M的 P上偷取 G来运行,偷取的个数通常是其他P运行队列的一半;如果还没有获取到g,则m就处于自旋状态。(work-stealing 机制)
调度时机:G 执行阻塞操作(如系统调用、通道操作)时,M 会释放 P,这时P变成了空闲,其他空闲的M就会绑定P执行其他的使用。当阻塞操作完成,G 会重新加入队列等待调度。

同一时刻,一个 P 只能绑定一个 M,而该 M 也只能执行一个 G。

2.GMP能不能去掉P层?会怎么样?

分析:

        主要考察对p的作用的理解,因为在期初的时候,是单纯的gm模型,是没有p的,为什么会被弃用呢?假设没有p的话,也就没有本地p的g队列,则所有的m都将去同一个全局队列获取可用g,这样势必会有锁竞争问题,所以回答可以抓住这个点,从性能加以分析。

回答:

        每个P有自己的本地队列,大幅度的减轻了对全局队列的直接依赖,所带来的效果就是锁竞争的减少。而 GM模型的性能开销大头就是锁竞争。

        每个 P相对的平衡上,在 GMP 模型中也实现了 Work Stealing 算法,如果P的本地队列为空,则会从全局队列或其他 P的本地队列中窃取可运行的 G 来运行,减少空转,提高了资源利用率。

3.M 和P的数量问题?

分析:

其实是上一个问题的补充问题,考察对gmp模型的了解深不深入,

P的数量:

        由启动时环境变量 $GOMAXPROCS 或者是由 runtime 的方法 GOMAXPROCS()决定。

M的数量:

        go语言本身的限制:go程序启动时,会设置M的最大数量,默认10000。但是内核很难支持这么多的线程数。

        runtime/debug中的SetMaxThreads函数,设置M的最大数量。

        一个M阻塞了,会创建新的M。

G的数量:

        理论上没有限制,受限于内存,但是goroutine过多会影响程序性能。

4、进程、线程、协程有什么区别?

分析:

        进程,线程,还有协程都是并发单元,但是具体又有不同,在分析三者区别的时候可以从大小,调度,资源分配还有用户态或者是内核态等几个方面进行分析。

回答:

        进程可以理解为一个动态的程序,进程是操作系统资源分配的基本单位,而线程是操作系统调度的基本单位,进程独占一个虚拟内存空间,而进程里的线程共享一个进程虚拟内存空间。线程的粒度更小,一个进程可以有多个线程协程可以理解为用户态线程,跟线程的区别主要有三个方面:

1.内存占用大小,协程大小为2k,可以动态扩容,而线程大小为2m,协程更轻量;

2.线程切换需要用户态到内核态的切换,而协程的切换不用,只在用户态完成,线程切换需要保存各种寄存器,而协程切换只需要保存rsp,rip,rbp三个寄存器,协程切换消耗更小。

3.通信方式:进程需要使用操作系统的进程间通信,通道、共享内存、socket等

                     线程通信主要使用共享内存

                      协程直接使用channel

http://www.dtcms.com/a/461835.html

相关文章:

  • 谷歌英文网站简单的网站php开发教程
  • 免费一键自助建站官网域名及对应网站
  • AI编程Cursor最强竞争对手来了,CodeX三种操作系统喂饭级安装教程!
  • Spring Cloud Alibaba 最新五大核心组件
  • 融乐Mini1.9.3 | 支持在线播放,本地播放,内置两条线路,免费畅听全网音乐
  • 车行网站源码微信公众平台营销
  • 客户端加密 和 服务端加密:端到端安全的真正含义
  • 88-python电网可视化项目-8-1
  • 做网站要自己租服务器吗wordpress打开速度优化
  • 要看网站是多少建设一个网站需要哪些费用
  • 物联网时代下无锡漫途科技无线多参数遥测终端助力饮水安全监测
  • 公司网站建设款计什么科目wordpress jquery版本
  • 麒麟系统如何设置.sh文件的图标
  • 3D GPR切片图
  • 深圳建设网站制作公司怎样制作一个网页
  • 腾讯云手机适用于哪些人群
  • 云南技术网站建设销售编程代码入门教学
  • 【PalladiumZ2 使用专栏 5 -- 模拟电路是否可以仿真?】
  • 公司网站文化活动备案上海企业建站方案
  • AI智能体开发实战(开源版)
  • 手动添加 SSH 私钥到 ssh-agent 以解决Permission denied (publickey) 错误
  • 用网站建设费用wordpress网站后台
  • 大模型前世今生(八):大模型的预训练
  • Tiff编码解码器封装
  • Android 性能优化 — Profiler 使用指南
  • DynamoDB 到 Redshift Zero-ETL 集成:完整实施指南
  • 长沙软件公司排行-专业软件开发公司
  • 深圳网站建设电话wordpress linux 伪静态
  • 缺少需求评审会导致哪些严重后果?
  • 176.在vue3中使用OpenLayers实现上传 CSV 文件并导出为 GeoJSON