协程Coroutine

协程Coroutine,在执行时,可以中断,转而运行其他协程,且在适当的时候,又可以返回原有子程序继续执行。

coroutine 协程 VS subroutine 子程

子程序的调用,只有一个入口,一次退出。而协程不同,一个协程退出执行转而去执行别的协程,而别的协程执行到一定条件可以返回原先的协程去继续执行。

从程序的表现上,协程有点像线程切换。但协程的特点是在一个线程内。协程之间的切换是由程序自身控制,而不是线程切换。因此,没有锁和线程切换的开销,性能较线程更好。

子程序 是通过堆栈来执行流。而coroutine采用Continuation,Continuation利用了当前的堆栈帧和指令指针,并将其封装到一个可调用的实体(continuation)中,并使用这个 continuation 作为惟一的参数调用另外一个函数。continuation 是一个可调用实体,它只可以接收一个参数,这个参数然后会返回到创建这个 continuation 的地方。
  
  这样的调用方式最大的好处就是,它可以让你从任意一个节点跳到另一个节点。而不必遵循堆栈方式的一层一层的return方式。比如说,在当前的函数内,你只要有一个其它函数的节点信息,完全可以选择return到那个函数,而不是循规蹈矩地返回到自己的调用者。你也可以在一个函数的任何位置储存自己的上下文信息,然后,在以后某个适当的时刻,从其它的任何一个函数里面返回到自己现在的位置。

python 中协程使用

Python对协程的支持是通过generator实现的。Python的yield不但可以返回一个值,它还可以接收调用者发出的参数。

来看下生产消费者的一个例子


def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

c = consumer()
produce(c)

执行结果:


[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

注意到consumer函数是一个generator,把一个consumer传入produce后:

首先调用c.send(None)启动生成器,consumer执行到到yield,返回producer执行

然后,producer一旦生产了东西,通过c.send(n)切换到consumer执行;

consumer通过yield拿到消息,处理,又通过yield把结果传回;

produce拿到consumer处理的结果,继续生产下一条消息;

produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

你可能感兴趣的:(协程Coroutine)