大家好呀,我是码财同行。今天咱们继续聊聊协程。
关于协程的文章网上有很多,但是大部分看完都是云里雾里的,要么摆理论,要么直接上代码,实际的效果并没有那么好。
我自己有很多年协程的使用经验,有C++,也有Golang的,算是对协程有一定的了解。在本文中,我将以自己的理解帮大家系统梳理一下协程的工作机制,力求做到简单易懂。
话不多说,直接开始~
程序执行的本质
首先,在正式学习协程之前,咱们要理解程序执行的本质。毕竟,协程相关的知识还是没有脱离程序执行的基本要素。就好比,咱们在学跑之前,先把走路学会了。
从宏观上来说,程序执行就是计算机硬件执行程序代码,完成特定任务的过程。在这个过程中,可以有特定的输入参数,而输出就是任务完成后的结果。
那具体又是如何执行的呢?我们可以将上图中的元素进一步分解和转换。
计算机硬件可以简略的分成执行指令的 CPU 和存储数据的内存:
程序代码中的代码片段可以被翻译成 CPU 可以理解的指令;输入参数和程序代码中的一些数据可以组成程序执行时的数据:
此时,从微观上来说,程序执行就是CPU执行指令,读写内存中的数据的过程。
程序的执行流
好,现在我们再来理解一下程序执行流的概念。
不同类型的执行流
前面我们刚刚讲到了一个简单程序的执行是这样的:
对于计算机硬件来说,面对的任务(程序代码)可以有很多个的,毕竟一台计算机上肯定有很多程序需要执行嘛~
这样,对应关系就变成了下面这样,计算机硬件需要在多份程序代码中切换,一会执行A,一会执行B,一会执行C ...
这就是所谓的 CPU 分时调用,就是因为计算机硬件中 CPU 在任一时刻是需要被程序独占的,而内存可以被多个程序共享,大家都把数据存在内存中。
随着计算机技术的发展,有了线程机制。一个程序中的代码片段可以通过线程做分工,例如,一个线程负责网络,一个线程负责逻辑任务,他们互不干扰。
在这里,我们把分工后的代码片段看成一个个独立的执行流,有两个线程就对应两个执行流。
再进一步,有人又提出了协程的机制。协程,本质上就是对任务(程序代码)逻辑上的进一步拆分:只要你认为程序中相对独立的代码片段都可以构成一个个协程,它相对于线程分工来说,拆分的粒度更细。
为了方便大家理解,我这里举一个例子。比如,玩家在玩一个游戏中的公会玩法,玩家操作完成后,程序需要做对玩家执行一些逻辑(比如加一些金币),然后还需要执行公会相关的逻辑(比如增加玩家所在公会的经验),还要给玩家发送一封奖励邮件等等。
上面任务逻辑的多个部分其实是相互独立的,可以作为一个个独立的执行流单独执行,而且互不干扰。
我们就可以把这多个代码片段放到一个个协程中执行。用 golang 的伪代码表示就是下面这样:
golang
func HandleLogic() {
//开始执行工会玩法逻辑
//增加玩家金币
AddPlayerCoin()
//开启协程,执行工会逻辑
go func() {
//增加工会经验
AddGuildExp()
}()
//开启协程,发送邮件
go func() {
SendPlayerMail()
}()
// 其他逻辑
}
现在,程序代码的执行变成了下面这样多样化的情况:
不管是单独一个程序,还是包含线程、协程,每个代码片段都对应的是一个个单独的执行流。
同样的,计算机硬件需要在多个单独的执行流中切换。这种计算机需要处理多个执行流的情况称为 并发。
执行流的切换
程序的逻辑可以被拆分成多个执行流/代码片段。CPU 在并发执行多个执行流的时候,需要按照一定规则依次切换执行,最大限度的 保证公平,使得每个执行流从时间轴上来看都是持续执行的。
如果是单 CPU 硬件,就需要将时间切分成时间片,一会执行这个,一会执行那个。
如果硬件有多核 CPU,则执行也是类似的,多个执行流可能被分配在多个 CPU 上执行。这个时候多个执行流才可能 并行 执行的。
那对于特定一个 CPU 来说,在该 CPU 上执行的多个执行流是有一个切换的过程。我们都学过,对于进程和线程执行流来说,这个切换是由操作系统负责的,操作系统保存好前一个执行流的上下文之后,通过调度算法选择下一个执行流,就可以执行下一个执行流了,细节这里不讨论。
我们要重点说明的是协程的切换过程,但基本原理是类似的,我们详细说一下。
下面是添加了切换流程的协程执行过程:
但具体要怎么切换呢?
这里就涉及程序执行的微观细节。
概括来说涉及以下几个方面:
- 上下文到底是啥?执行的代码切走指什么?
- 调度:下一个待执行的协程怎么选?
- 上下文处理:寄存器与栈的处理
详细的,我们下一篇文章来谈,敬请期待。
好了,看了这么多,一定很费脑力吧。来个笑话放松一下 :)
【笑话一则】喝多了准备打车回家,本来想叫嘀嘀打车,结果叫成了滴滴代驾。等代驾到了,我们对视了10秒,异口同声得说:"你车呢?"
最后,请大家来个点赞、收藏、转发吧,您的鼓励是我持续创作的动力,蟹蟹!