通過廖雪峰的Python3學習教程網站學習與整理以下內容。
概念
協程,英文名:Coroutine
- 協程是單線程執(zhí)行模式,因其執(zhí)行切換是由代碼自身控制,故有極高的執(zhí)行效率。與多線程相比,協程數量越多,協程的性能優(yōu)勢就越明顯。
- 不需要多線程的鎖機制,不存在同時寫變量的沖突。在協程中控制共享資源不加鎖,只需要判斷狀態(tài)即可,故執(zhí)行效率比多線程高很多。
- 因其是單線程模式,故采用 多進程+協程 的方式,充分利用CPU多核的計算處理能力,充分發(fā)揮其高效率。
協程執(zhí)行流程:
協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。因此協程能保留上一次調用時的狀態(tài)(即所有局部狀態(tài)的一個特定組合),每次過程重入時,就相當于進入上一次調用的狀態(tài),換種說法:進入上一次離開時所處邏輯流的位置。
實現方式
- python 對 協程的支持是通過 generator(生成器) 實現的
- 生成器Tips:
- 可以使用 for 循環(huán)迭代
- 可以使用 next() 迭代
- 可以使用 send() 迭代
- yield value 不但可以返回一個值,也可以接受調用者發(fā)出的參數(在下面的代碼示例中中能充分說明)
代碼示例及說明
def consumer():
r = ''
while True:
# yield 返回 r, 并將 producer() 中 c.send(n)中的 n 賦值給 consumer中的 n
n = yield r
if not n:
return
print('[PRODUCER] Consuming %s...{}'.format(n))
r = '200OK!'
def producer(m):
m.send(None)
n = 0
while n < 5:
n += 1
print('[PRODUCER] Producing %s...{}'.format(n))
# producer 通過 send() 將變量 n 作為參數傳給 consumer 中 yidle 接收的參數,
# 并且將 yield 的返回值 賦給 res
res = m.send(n)
print('[PRODUCER] Consumer Return %s...{}'.format(res))
if __name__ == '__main__':
c = consumer()
producer(c)
執(zhí)行流程:
- 執(zhí)行腳本,首先執(zhí)行 if _name_ == '_main_'中的代碼塊
- 首先 produce() 函數執(zhí)行c.send(None) ,啟動生成器,consumer() 遇到 n = yield r ,此時 r = '', yield 返回 空 并停止執(zhí)行,進入等待
- produce()進入while循環(huán),q = 0 + 1 = 1,打印“[PRODUCER] Producing %s...1”
- res = c.send(q) 。 將 1 傳給consumer() ,此時 n = 1,if 判斷條件為False。并且打印 [PRODUCER] Consuming %s...1。r 被重新賦值為 '200OK!' 。
- 因為死循環(huán),程序再次執(zhí)行到 n = yield r ,程序停止運行,進入等待。
- producer() 函數中第19 行 res 接收 上述 yield 返回的 r 變量,即'200OK!' 。
- 打?。篬PRODUCER] Consumer Return %s...200OK!
- 接下來的從第 4 步開始循環(huán)執(zhí)行。
以上部分可以發(fā)現,consumer 內部一直被中斷,去執(zhí)行 producer 中的程序。而不是 consumer 完全執(zhí)行完。
這一點一定要吃透,否則無法理解 async 異步的流程。