协程(一)快速理解协程的定义和分类
2016-08-19 15:22
323 查看
协程的概念很早以前就被提出,很多语言也实现了协程,例如Erlang,Lua。不过我首次接触协程是在学习golang的过程中,当真正使用协程的时候就被它的优雅和高效所折服,这也埋下了自己对协程好奇的种子。随着接触许多C++协程库,例如云风的coroutine、腾讯的libco、魅族的libgo等,很多当时模糊的概念也逐渐清晰。
云风的coroutine代码简介,实现了非对称的stackful协程,非常适合用来入门。笔者fork了该库,并根据自己对协程工作原理的理解为该库添加了注释,详细可参考我的github.
协程是例程(过程、函数、方法、子程序)的范化概念。协程和例程的主要区别是,协程通过保持执行状态可以能够明确的挂起和恢复,协程通过维护上下文提供了增强的控制流。
2004年Lua的作者Ana Lucia de Moura和Roberto Ierusalimschy发表的论文Revisiting Coroutines中,对协程进行了分类,论文中依照三个问题区分协程:
控制传递(Control-transfer)机制
协程是否为栈式(Stackful)构造
协程是否作为语言的第一类(First-class)对象提供
解决方法则是让每个协程拥有自己的栈和控制块(control-block)。在协程挂起前,该协程的non-volatile寄存器值(包括stack、instruction/program pointer)被保存在该协程对应的control-block中。新激活协程在恢复前,它在control-block中存储的寄存器值被恢复到CPU的寄存器中。
上下文切换无需系统权限,为协作式多任务提供了方便。协程提供了并行性,例如当程序在同时做多件事情时,相比于只用一个单独的控制流,协程可以更加简单而优雅的做到这一点。
非对称协程知道它的调用者,其在挂起时转让控制权给它的调用者,然后调用者根据算法调用其他非对称协程进行工作。相比之下,所有的对称协程都是等价的,控制权直接在对称协程之间进行传递,即对称协程在挂起时主动指明另外一个对称协程来接收控制权。
如果没有stackfulness和irst-class对象的语义,协程的能力将被限制。
《理解Lua的Coroutine》
《协程(一)协程的定义与分类》
《一个”蝇量级”C语言协程库》
云风的coroutine代码简介,实现了非对称的stackful协程,非常适合用来入门。笔者fork了该库,并根据自己对协程工作原理的理解为该库添加了注释,详细可参考我的github.
协程的定义
在计算机科学中,例程(过程、函数、方法、子程序)被定义为操作的序列。例程的执行形成了父子关系,且孩子例程总是在父例程前结束。举例说明,main函数中调用函数func1,func1中调用函数func2,此时就形成了父子关系(main为func1的父例程,func1是func2的父例程),func2执行结束进行函数栈回退,然后func1继续执行直到结束后进行函数栈回退,最后main继续执行直到结束后进行函数栈回退并退出程序。协程是例程(过程、函数、方法、子程序)的范化概念。协程和例程的主要区别是,协程通过保持执行状态可以能够明确的挂起和恢复,协程通过维护上下文提供了增强的控制流。
2004年Lua的作者Ana Lucia de Moura和Roberto Ierusalimschy发表的论文Revisiting Coroutines中,对协程进行了分类,论文中依照三个问题区分协程:
控制传递(Control-transfer)机制
协程是否为栈式(Stackful)构造
协程是否作为语言的第一类(First-class)对象提供
协程如何工作
如果协程像例程一样,那么函数栈将会随着每次调用而增长、并且从不退栈。跳转到中间某个协程则是不可能的,因为函数栈的栈顶才能进行退栈操作。解决方法则是让每个协程拥有自己的栈和控制块(control-block)。在协程挂起前,该协程的non-volatile寄存器值(包括stack、instruction/program pointer)被保存在该协程对应的control-block中。新激活协程在恢复前,它在control-block中存储的寄存器值被恢复到CPU的寄存器中。
上下文切换无需系统权限,为协作式多任务提供了方便。协程提供了并行性,例如当程序在同时做多件事情时,相比于只用一个单独的控制流,协程可以更加简单而优雅的做到这一点。
控制传递机制
根据控制传递机制的不同区分出了对称协程和非对称协程。非对称协程知道它的调用者,其在挂起时转让控制权给它的调用者,然后调用者根据算法调用其他非对称协程进行工作。相比之下,所有的对称协程都是等价的,控制权直接在对称协程之间进行传递,即对称协程在挂起时主动指明另外一个对称协程来接收控制权。
stackfulness
对比stackless协程,stackful协程可以在内部的嵌套函数中被挂起,在挂起点恢复执行。而stackless协程仅能在顶层部分被挂起。first-class对象
协程被作为first-class对象提供,那么其可以作为参数被传递,由函数创建并返回,并存储在一个数据结构中供后续操作,也可以被开发者自由的维护。从上面的描述可以看到,first-class对象主要为协程提供了良好的表达力,方便开发者对协程进行操作。如果没有stackfulness和irst-class对象的语义,协程的能力将被限制。
参考资料
《Coroutine - Wiki》《理解Lua的Coroutine》
《协程(一)协程的定义与分类》
《一个”蝇量级”C语言协程库》
相关文章推荐
- 协程(一)协程的定义与分类
- 快速理解索引原理、分类、特点
- 《WCF技术内幕》翻译6:第1部分_第2章_面向服务:概述、快速定义面向服务、理解消息
- 理解Linux环境变量及配置文件执行顺序 博客分类: Linux 每个用户都有自己专属的运行环境,这个环境是由一组变量所定义,这些变量称之为环境变量。用户可以修改环境变量以满足自己的要求。
- 协程(一)协程的定义与分类
- 《WCF技术内幕》翻译6:第1部分_第2章_面向服务:概述、快速定义面向服务、理解消息
- 快速学习COSMIC方法之七:如何理解功能处理的定义?
- 问题解答之 计算机中寄存器定义,分类
- 几种设计模式分类的个人理解
- 多态分类-强制多态,参数多态,过载多态,包含多态的理解
- 理解 Delphi 的类(十一) - 深入类中的方法[2] - 关于覆盖与重定义
- 快速理解.NET Framework[翻译]
- 整理理解子网掩码,及快速划分
- 理解快速生成树协议(802.1w)
- 理解Javascript中类的定义
- 理解Javascript中类的定义-补充
- 理解 Delphi 的类(十) - 深入方法[1] - 定义
- 快速分类递归算法改写成迭代算法
- 数据仓库定义的理解。
- 三分钟快速理解MDA——模型驱动架构