goroutine原理的图文详解
Go语⾔运⾏时环境提供了⾮常强⼤的管理goroutine和系统内核线程的调度器, 内部提供了三种
对象: Goroutine, Machine, Processor。
在宏观上说, Goroutine与Machine因为Processor的存在,形成了多对多(M:N)的关系。 M个
⽤户线程对应N个系统线程,缺点增加了调度器的实现难度。
Goroutine是Go语⾔中并发的执⾏单位。 Goroutine底层是使⽤协程(coroutine)实现, coroutine
是⼀种运⾏在⽤户态的⽤户线程(参考操作系统原理:内核态,⽤户态)它可以由语⾔和框架层
调度。 Go在语⾔层⾯实现了调度器,同时对⽹络, IO库进⾏了封装处理,屏蔽了操作系统层⾯的
复杂的细节,在语⾔层⾯提供统⼀的关键字⽀持。
三者与内核级线程的关系如下图所示:
⼀个Machine会对应⼀个内核线程(K),同时会有⼀个Processor与它绑定。⼀个Processor连接
⼀个或者多个Goroutine。 Processor有⼀个运⾏时的Goroutine(上图中绿⾊的G),其它的
Goroutine处于等待状态。
Processor的数量同时可以并发任务的数量,可通过GOMAXPROCS限制同时执⾏⽤户级任务的操
作系统线程。 GOMAXPROCS值默认是CPU的可⽤核⼼数,但是其数量是可以指定的。
当⼀个Goroutine创建被创建时, Goroutine对象被压⼊Processor的本地队列或者Go运⾏时
全局Goroutine队列。
Processor唤醒⼀个Machine,如果Machine的waiting队列没有等待被 唤醒的Machine,则
创建⼀个(只要不超过Machine的最⼤值, 10000), Processor获取到Machine后,与此
Machine绑定,并执⾏此Goroutine。
Machine执⾏过程中,随时会发⽣上下⽂切换。当发⽣上下⽂切换时,需要对执⾏现场进⾏
保护,以便下次被调度执⾏时进⾏现场恢复。 Go调度器中Machine的栈保存在Goroutine对
象上,只需要将Machine所需要的寄存器(堆栈指针、程序计数器等)保存到Goroutine对象上
即可。
如果此时Goroutine任务还没有执⾏完, Machine可以将Goroutine重新压⼊Processor的队
列,等待下⼀次被调度执⾏。
如果执⾏过程遇到阻塞并阻塞超时, Machine会与Processor分离,并等待阻塞结束。此时
Processor可以继续唤醒Machine执⾏其它的Goroutine,当阻塞结束时, Machine会尝
试”偷取”⼀个Processor,如果失败,这个Goroutine会被加⼊到全局队列中,然后Machine
将⾃⼰转⼊Waiting队列,等待被再次唤醒。
Go依赖于称为CSP(Communicating Sequential Processes)的并发模型,通过
Channel实现这种同步模式。
向channel写数据
<pre><code> 向⼀个channel中写数据简单过程如下: 1. 如果等待接收队列recvq不为空,说明缓冲区中没有数据或者没有缓冲区,此时直接从recvq取出G,并把数据写⼊,最后把该G唤醒,结束发送过程; 2. 如果缓冲区中有空余位置,将数据写⼊缓冲区,结束发送过程; 3. 如果缓冲区中没有空余位置,将待发送数据写⼊G,将当前G加⼊sendq,进⼊睡眠,等待被读goroutine唤醒; </code></pre> </li><li>从channel读数据
<pre><code> 从⼀个channel读数据简单过程如下: 1. 如果等待发送队列sendq不为空,且没有缓冲区,直接从sendq中取出G,把G中数据读出,最后把G唤醒,结束读取过程; 2. 如果等待发送队列sendq不为空,此时说明缓冲区已满,从缓冲区中⾸部读出数据,把G中数据写⼊缓冲区尾部,把G唤醒,结束读取过程; 3. 如果缓冲区中有数据,则从缓冲区取出数据,结束读取过程; 4. 将当前goroutine加⼊recvq,进⼊睡眠,等待被写goroutine唤醒; </code></pre> </li></ul> <ul><li>关闭channel
<pre><code> 关闭channel时会把recvq中的G全部唤醒,本该写⼊G的数据位置为nil。把sendq中的G全部唤醒,但这些G会panic。 除此之外, panic出现的常⻅场景还有: 1. 关闭值为nil的channel 2. 关闭已经被关闭的channel 3. 向已经关闭的channel写数据 </code></pre> </li></ul> 到此这篇关于“goroutine原理的图文详解”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!您可能感兴趣的文章:
golang 深入浅出之 goroutine 理解
Goroutine的调度分析(一)
Go:Goroutine 的切换过程实际上涉及了什么
[Go 教程系列笔记] goroutine(协程)
goroutine 调度器
golang goroutine 通知_深入golang之---goroutine并发控制与通信
goroutine原理的图文详解
GO 语言之 Goroutine 原理解析
Golang中Goroutine与线程
Goroutine并发调度模型深度解析&手撸一个协程池