拥抱新技术 —— 协程

文章目录非对称协程和对称协程独占栈和共享栈定时器参考文献
写在前面:
【拥抱新技术 —— 协程】本文主要针对使用C/C++或有C/C++基础的读者 , 讨论的开源网络库libco
什么是协程
很多人描述协程为 “轻量级线程” 、 “用户态线程” 等等 。之前博主对这个东西也很迷惑?
这都是啥!!!不急 , 博主将会写一系列文章来理清楚协程 , 此为系列文章的第一篇 , 主要介绍协程的一些基本知识:
为了理清楚协程 , 我们还得对线程的概念进行回忆一下:

线程是操作系统能够进行运算调度的最小单位 。被包含在进程之中 , 是进程的实际运作单位 。一条线程指的是进程中一个单一顺序的控制流 , 一个进程可以并发执行多个线程 , 每个线程会执行不同的任务 。对应在现实生活中 , 进程是组长 , 线程是小组成员 。
既然说线程是系统调度的最小单位 , 那么又何来说协程的概念呢?通过阅读大量的文献以及之后 , 我对协程有了自己的看法 。
下面我将一条一条来解读这些特性:
协程之于线程
刨除操作系统CPU对线程调度的因素 , 我们就单考虑一个线程之中的情况 。
首先 , 协程之于线程跟线程之于进程是一样的 , 一个线程之中是有多个协程的 。

拥抱新技术 —— 协程

文章插图
可以把线程想象成一个单核CPU , 而协程A、B都是原来的进程 。协程A、B通过一个叫协程调度器的东西来负责协程A、B的交替执行 。
注:
以上情况只涉及libco 中的设计 , go语言中的协程其可以运行在多个“CPU”(线程) 。
在libco中 , 一个协程只能运行在一个线程中 , 这也就是说它为什么在线程中是串行的原因 。因为对于一个单核CPU中 , 也没法进行两个进程的并行啊 。
协程的切换
切成的切换得益于其在用户态就保存了栈和寄存器信息 。这里面有当前协程的状态信息 , 有下一条执行的地址信息 。这么说有点抽象 , 我们看一下下面的一个例子吧:
假设协程A正在执行以下函数:
void funa(void){int a = 10;int b = 20;sum(a,b);}
如果说当协程A执行到sum函数的时候 , 协程调度器调度协程B , 协程A的信息就会被保存起来 。那么当前协程的的运行状态信息就是 a=10 , b=20 , 下一条该执行的函数是sum 。等待下次协程A被调度器调度 , 这些信息就会被恢复 , 再次从协程A去执行 。
非对称协程和对称协程
协程目前分两种 , 一种是go语言采用的对称协程;一种是libco采用的非对称协程 。
这里借用知乎博主tx征服者的图来向大家说明:
对称协程其实就是由协程调度器来负责 , 协程不允许调度其他协程 。调度器协程A , 那么协程A会yeild回调度器 , 再由调度器去执行其他的协程 。如果我们把的虚线都放在左边 , yeild的实线都放在右边 。以调度器为中心 , 那么他是不是就是一个对称的图形呢?
我们再来看一下非对称协程:
拥抱新技术 —— 协程

文章插图
非对称调度由调度器来调度协程A , 然后协程A再调动协程B 。那么让出CPU使用权就不是让给调度器了 , 而是协程A 。简而言之就是从哪儿来 , 回哪儿去 。