通过廖雪峰的Python3学习教程网站学习与整理以下内容。
概念
协程,英文名:Coroutine
- 协程是单线程执行模式,因其执行切换是由代码自身控制,故有极高的执行效率。与多线程相比,协程数量越多,协程的性能优势就越明显。
- 不需要多线程的锁机制,不存在同时写变量的冲突。在协程中控制共享资源不加锁,只需要判断状态即可,故执行效率比多线程高很多。
- 因其是单线程模式,故采用 多进程+协程 的方式,充分利用CPU多核的计算处理能力,充分发挥其高效率。
协程执行流程:
协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
实现方式
- python 对 协程的支持是通过 generator(生成器) 实现的
- 生成器Tips:
- 可以使用 for 循环迭代
- 可以使用 next() 迭代
- 可以使用 send() 迭代
- yield value 不但可以返回一个值,也可以接受调用者发出的参数(在下面的代码示例中中能充分说明)
代码示例及说明
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)
执行流程:
- 执行脚本,首先执行 if _name_ == '_main_'中的代码块
- 首先 produce() 函数执行c.send(None) ,启动生成器,consumer() 遇到 n = yield r ,此时 r = '', yield 返回 空 并停止执行,进入等待
- produce()进入while循环,q = 0 + 1 = 1,打印“[PRODUCER] Producing %s...1”
- res = c.send(q) 。 将 1 传给consumer() ,此时 n = 1,if 判断条件为False。并且打印 [PRODUCER] Consuming %s...1。r 被重新赋值为 '200OK!' 。
- 因为死循环,程序再次执行到 n = yield r ,程序停止运行,进入等待。
- producer() 函数中第19 行 res 接收 上述 yield 返回的 r 变量,即'200OK!' 。
- 打印:[PRODUCER] Consumer Return %s...200OK!
- 接下来的从第 4 步开始循环执行。
以上部分可以发现,consumer 内部一直被中断,去执行 producer 中的程序。而不是 consumer 完全执行完。
这一点一定要吃透,否则无法理解 async 异步的流程。
网友评论