Coroutine(协程)模式与线程

时间:2021-07-02 20:03:16

概念

协程(Coroutine)这个概念最早是Melvin Conway在1963年提出的,是并发运算中的概念,指两个子过程通过相互协作完成某个任务,用它可以实现协作式多任务,协程(coroutine)技术本质上是一种程序控制机制。比如,消费者/生产者,你走几步,我走几步;下棋对弈,你一步我一步。
Coroutine(协程)可以分为:

    • 非对称式(asymmetric)协程,或称半对称式(semi-asymmetric)协程,又或干脆就叫半协程(semi-coroutine)
    • 对称式(symmetric)协程。

非对称式(asymmetric)协程之所以被称为非对称的,是因为它提供两种传递程序控制权的操作:一种是重调用协程,另一种是挂起协程,并将程序控制权返还给调用者。

而对称式协程的特点是只有一种传递程序控制权的协程,即将控制权传递给指定的协程。

 

线程和协程的异同

协程(Coroutine)类似于线程(Thread)的地方是:每个协程都有有自己的堆栈,自己的局部变量。

线程和协程的主要区别在于:
 1. 线程可以并发运行,线程之间是不能共写全局变量(写冲突)。
 2. 协程不能并发运行,协程之间可以共享全局变量(不会存在写冲突)。

协程的状态

协程有三种状态:挂起(suspended),运行(running),停止(dead)。
当我们创建一个协程时他开始的状态为挂起态,也就是说我们创建协程的时候不会自动运行。

st = co.status;

激活协程

IsSucessful := co.resume();

激活挂起的协程,使协程继续运行。参数co是一个协程对象。

如果协程是挂起状态,则继续运行,resume函数返回true。如果协程已经停止或者遇到其他错误,resume函数返回false。

挂起协程

co.yield([...]);

挂起当前协程。直到协程被外部协程使用CoRoutine.Resume再次激活,将返回到执行CoRoutine.Yield函数后的地方继续执行。
CoRoutine.yield的参数将传递给SaveYieldedValue虚方法,你需要重载该方法处理。

当一个协程正在运行时,不能在外部终止它.只能在协程内部调用coroutine.yield挂起当前协程。
不需要考虑协程安全、协程同步的问题。协程的代码比线程的代码更容易编写。

“控制”和“行为”的复用

在很多时候,我们需要对数据结构(如:List,Stack)中的元素按某种要求进行遍历,我们称之为“控制”;然后对目标元素进行某个操作(如,显示该元素),我们称之为“行为”。许多情况下,这种“控制”或行为的代码本来是可以被复用的,但是因为难以将这其中的“控制”和“行为”分离,造成了我们不得不一遍又一遍的书写这些类似的代码(虽然利用回调可以实现在一定程度上的“控制”和行为的分离,但是并不优雅,也不无法实现彻底重用)。举例来说就像是典型的生产者消费者模型。