協程技術研究

先記住一句話,子程序是協程的一種特例。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-人人均可以實現的簡單協程庫

相關文章
相關標籤/搜索