关键词
coroutine、yield、next、send
协程(coroutine)
协作式多任务的子程序,允许执行被挂起与被恢复。相对于子程序而言,协程更为通用和灵活。
协程可以通过yield来调用其他协程,接下来的每次协程被调用时,从协程上次yield返回的位置接着执行,通过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的。
协程与子进程的对比
- 子进程可以调用其他子进程,调用者等待被调用者结束后继续执行,子进程的生命期遵循后进先出,即最后一个被调用的子进程最先结束返回。协程的生命期完全由对它们的使用需要来决定。
- 子进程的起始处是唯一的入口点,每当子进程被调用时,执行都从被调用的子进程的起始处开始。协程可以有多个入口点,协程的起始处是第一个入口点,每个yield返回出口点都是再次被调用执行时的入口点
- 子进程只在结束时一次性的返回全部结果值。协程可以在yield时不调用其他协程,而是每次返回一部分的结果,这种协程称作生成器或者迭代器
- 现代的指令集架构通常提供对调用栈的指令支持,便于实现可递归调用的子进程。在提供续体的语言环境下,恰好可用控制状态抽象表示来实现协程
伪代码
1 | var q := new 队列 |
同线程比较
协程非常类似与线程,但是协程是协作式多任务的,典型的线程是内核级抢占式多任务的。协程提供并发行而非并行性,协程超过线程的好处是它们可以用于硬性实时的语境(在协程之间的切换不需要涉及任何系统调用或者任何阻塞调用),这里不需要守卫关键区块的同步性原语(primitive)如互斥锁、信号量等,并且不需要来自操作系统的支持。有可能以一种对调用代码透明的方式,使用抢占式调度的线程实现协程,但会失去某些优势(特别是对硬性实时操作系统的适合性和相对廉价的相互之间切换)
用户级线程是协作式多任务的轻量级线程,概念上上和协程一样。区别在于协程是语言级别的狗仔,可以看作是一种流程控制,而线程是系统层级的构造。
生成器
生成器也叫半协程,是协程的子集。尽管二者都可以yield多次,暂停suspend自身的执行,并允许在多个入口点重新进入,但是它们的差异在于,协程有能力控制在它让位之后哪个协程立即续接它来执行,而生成器不能,他只能把控制权转交给调用者。在生成器的yield语句不指定要跳转到的协程,而是向父进程传递返回值.
可以在生成器设施之上实现协程,这需要通过顶层的分派器历程的援助,它显示的把控制权传递给生成器传回的记号所指定的另一个生成器
1 | var q := new 队列 |
生成器和迭代器的用法有着微妙的差异,生成器看起来像是函数而表现得像是迭代器。在python中生成器是迭代器的子构造,他是返回迭代器的函数
引用:wikipedia-协程