协程技术研究

先记住一句话,子程序是协程的一种特例。html

Python yield

Python 中的 yield 保存一个 generator 函数的状态,generator 是一个特殊类型的迭代器(iterator)git

import time

def consumer():
    r = ''
    while True:
        n = yield r
        print('[CONSUMER] Consuming %s...' % n)
        time.sleep(1)
        r = '200 OK'

def produce(c):
    c.next()
    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()

if __name__=='__main__':
    c = consumer()
    produce(c)

运行结果github

[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

yield 至关于 return,主动交出程序的控制权,只不过它的状态保存到了内存中,还会再把控制权要回来的。第一次调用 consumer().next() 时会运行到 consumer 的 yield 这一行,而后权限又跑到了 producer 中。运行到 producer send 这一行,把权限给 consumer。consumer 和 producer 之间经过 yield 和 send 轮换掌握控制权。这样就实现了非线程方式的抢占式多任务。微信

next() 和 send() 调用是同样的,next() 不能传参数。网络

微信协程库 libco

libco 代码见 github,支持的功能框架

1.协程的建立与调度,使用 co_create,co_resume,co_yield 来搭建协程服务。和 Python 的 yield 方式很相似异步

2.基于网络的协程调度框架,能够经过网络事件来进行协程调度函数

libco 能够将系统的同步操做异步化,如标准 read 函数读取文件,系统打开文件描述符,阻塞在这里,一旦读取完毕返回。异步化就是调用 read 后直接返回,设置一个函数来处理读取完毕后返回的数据。把事件(读取完数据)注入到 epoll 中,同时 yield 交出线程控制权,一旦事件到来,切换到这个协程进行处理。ui

经过 hack 的方式替换掉了 read 函数,同理也能够替换掉和网络读写有关的接口,这样能够适用于 RPC 框架,这就是 libco 的主要思想。.net

参考

Linux Select 使用

select、poll、epoll之间的区别总结

谈谈对协程的理解

ucontext-人人均可以实现的简单协程库

相关文章
相关标签/搜索