美文网首页
协程的理解(一)

协程的理解(一)

作者: 北游_ | 来源:发表于2018-06-15 09:51 被阅读12次

    通过廖雪峰的Python3学习教程网站学习与整理以下内容。

    原文地址:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432090171191d05dae6e129940518d1d6cf6eeaaa969000

    概念

    协程,英文名: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)
    

    执行流程:

    1. 执行脚本,首先执行 if _name_ == '_main_'中的代码块
    2. 首先 produce() 函数执行c.send(None) ,启动生成器,consumer() 遇到 n = yield r ,此时 r = '', yield 返回 空 并停止执行,进入等待
    3. produce()进入while循环,q = 0 + 1 = 1,打印“[PRODUCER] Producing %s...1”
    4. res = c.send(q) 。 将 1 传给consumer() ,此时 n = 1,if 判断条件为False。并且打印 [PRODUCER] Consuming %s...1。r 被重新赋值为 '200OK!' 。
    5. 因为死循环,程序再次执行到 n = yield r ,程序停止运行,进入等待。
    6. producer() 函数中第19 行 res 接收 上述 yield 返回的 r 变量,即'200OK!' 。
    7. 打印:[PRODUCER] Consumer Return %s...200OK!
    8. 接下来的从第 4 步开始循环执行。

    以上部分可以发现,consumer 内部一直被中断,去执行 producer 中的程序。而不是 consumer 完全执行完。
    这一点一定要吃透,否则无法理解 async 异步的流程。

    相关文章

      网友评论

          本文标题:协程的理解(一)

          本文链接:https://www.haomeiwen.com/subject/byspeftx.html