Go语言并发编程_GMP

由线程到协程

  • 进程:是应用程序的启动实例,拥有自己独立的资源。
  • 线程:从属于进程,没有自己独立的资源。只有程序计数器,一组寄存器以及栈。一个进程可以拥有多个线程。
    线程是CPU最小的执行单元,进程是最小的资源管理单元。
    在这里插入图片描述
    而线程和进程有一个明显的弊端就是切换成本很高。对于线程还要考虑同步问题。协程也就应运而生。
  • 协程:(Coroutines)是一种比线程更加轻量级的存在。一个进程拥有多个线程,一个线程也可以拥有多个协程。
    在这里插入图片描述
    协程跟线程是有区别的,线程由 CPU 调度是抢占式的,协程由用户态调度是协作式的,一个协程让出 CPU 后,才执行下一个协程。而用户态的协程的切换的速度就得到了极大的提升。

Go语言的协程

在Go语言中,协程被称为goroutine,十分轻量级,一个goroutine只占几KB。对比于进程使用虚拟内存的在32位系统上使用4GB,线程的大约4MB。如此的轻量级可以支持在有限的内存空间里使用大量的goroutine。当然goroutine的栈虽然只占几KB但是实际上是可以伸缩的,如果需要更多的空间runtime会为其进行分配。在运行时如果协程阻塞,该线程上的其他协程会被runtime调度,转到其他可运行的线程上。如此,以极低的成本支持了更高的并发。

Go中的协程调度器GMP模型

如其名该goroutine的调度器分为三个部分:G,P,M

  1. G(goroutine协程):代表一个goroutine对象,每次go调用的时候,都会创建一个G
  2. P(processor处理器):管理着一组goroutine队列,P里面会存储当前goroutine运行的上下文环境(函数指针,堆栈地址及地址边界),P会对自己管理的goroutine队列做一些调度(比如把占用CPU时间较长的goroutine暂停,运行后续的goroutine等等)当自己的队列消费完了就去全局队列里取,如果全局队列里也消费完了会去其他P的队列里抢任务。
  3. M(thread线程):go运行是对操作系统内核线程的虚拟,M与内核线程一般是一一映射的关系,一个goroutine最终是要放在M上执行的。
    在这里插入图片描述
    图中的内容:

全局队列(Global Queue):存放等待运行的 G。

P 的本地队列:同全局队列类似,存放的也是等待运行的 G,存的数量有限,不超过 256 个。新建 G’时,G’优先加入到 P 的本地队列,如果队列满了,则会把本地队列中一半的 G 移动到全局队列。

P 列表:所有的 P 都在程序启动时创建,并保存在数组中,最多有 GOMAXPROCS(可配置) 个。

M:线程想运行任务就得获取 P,从 P 的本地队列获取 G,P 队列为空时,M 也会尝试从全局队列拿一批 G 放到 P 的本地队列,或从其他 P 的本地队列偷一半放到自己 P 的本地队列。M 运行 G,G 执行之后,M 会从 P 获取下一个 G,不断重复下去。

Goroutine 调度器和 OS 调度器是通过 M 结合起来的,每个 M 都代表了 1 个内核线程,OS 调度器负责把内核线程分配到 CPU 的核上执行。

  • 有关 P 和 M 的个数问题
  • P 的数量:
    由启动时环境变量 $GOMAXPROCS 或者是由 runtime 的方法 GOMAXPROCS() 决定。这意味着在程序执行的任意时刻都只有 $GOMAXPROCS 个 goroutine 在同时运行。
  • M的数量:
    go 语言本身的限制:go 程序启动时,会设置 M 的最大数量,默认 10000. 但是内核很难支持这么多的线程数,所以这个限制可以忽略。
    runtime/debug 中的 SetMaxThreads 函数,设置 M 的最大数量
    一个 M 阻塞了,会创建新的 M。
  • P和M的数量关系:M 与 P 的数量没有绝对关系,一个 M 阻塞,P 就会去创建或者切换另一个 M,所以,即使 P 的默认数量是 1,也有可能会创建很多个 M 出来。
  • P和M的创建时机:

1、P 何时创建:在确定了 P 的最大数量 n 后,运行时系统会根据这个数量创建 n 个 P。
2、M 何时创建:没有足够的 M 来关联 P 并运行其中的可运行的 G。比如所有的 M 此时都阻塞住了,而 P 中还有很多就绪任务,就会去寻找空闲的 M,而没有空闲的,就会去创建新的 M。

更多原文见:http://www.topgoer.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值