Golang的GMP内存模型(一)

本文介绍了Go语言中的GMP模型,该模型解决了多线程切换的效率问题。GMP模型包括G(goroutine)、M(machine,即线程)和P(processor)。每个P包含一个可运行的G队列,M通过获取P来运行G。当P的数量(由$GOMAXPROCS决定)和M的数量动态调整,以优化系统的并发性能。在面对阻塞情况时,新的M会被创建以保持系统的运行。
摘要由CSDN通过智能技术生成

1.调度器的由来

在这里插入图片描述
1.早期的单进程操作系统在这里插入图片描述
缺点:单一执行流程、计算机只能一个一个业务处理

​ 进程阻塞所带来的CPU浪费时间

2.多进程/多线程操作系统
在这里插入图片描述
解决了阻塞问题,CPU轮询,进程切换需要保存状态,造成了巨大的时间浪费在这里插入图片描述
面临的问题是 线程越多,不停的切换轮询CPU,代价越大。所以在语言层面,让多个协程(任务绑定在一个线程内完成,可以减少线程切换)
在这里插入图片描述

在这里插入图片描述
N:1 带来的问题是 如果一个协程阻塞,同一个线程绑定的下一个协程就会持续等待

M:N 模型化解了问题,如果一个协程阻塞,可以绑定到下一个线程
在这里插入图片描述

2.GMP模型的设计思想

在调度器中,出列M(thread)和G(goroutine),又引进了P(Processor)。

在这里插入图片描述
Processor,它包含了运行goroutine的资源,如果线程想运行goroutine,必须先获取P,P中还包含了可运行的G队列。

1.GMP模型

在Go中,线程是运行goroutine的实体,调度器的功能是把可运行的goroutine分配到工作线程上
在这里插入图片描述

  1. 全局队列(Global Queue):存放等待运行的G。
  2. P的本地队列:同全局队列类似,存放的也是等待运行的G,存的数量有限,不超过256个。新建G’时,G’优先加入到P的本地队列,如果队列满了,则会把本地队列中一半的G移动到全局队列。
  3. P列表:所有的P都在程序启动时创建,并保存在数组中,最多有GOMAXPROCS(可配置)
  4. M:线程想运行任务就得获取P,从P的本地队列获取G,P队列为空时,M也会尝试从全局队列一批G放到P的本地队列,或从其他P的本地队列一半放到自己P的本地队列。M运行G,G执行之后,M会从P获取下一个G,不断重复下去。

2.P和M的数量问题

1、P的数量:

  • 由启动时环境变量$GOMAXPROCS或者是由runtime的方法GOMAXPROCS()决定。这意味着在程序执行的任意时刻都只有$GOMAXPROCS个goroutine在同时运行。在这里插入图片描述
    2、M的数量:

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

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

M与P的数量没有绝对关系,一个M阻塞,P就会去创建或者切换另一个M,所以,即使P的默认数量是1,也有可能会创建很多个M出来。

3.P和M何时会被创建

1、P何时创建:在确定了P的最大数量n后,运行时系统会根据这个数量创建n个P。

2、M何时创建:没有足够的M来关联P并运行其中的可运行的G。比如所有的M此时都阻塞住了,而P中还有很多就绪任务,就会去寻找空闲的M,而没有空闲的,就会去创建新的M。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值