有识

个人网 | 追寻一切真知灼见

用户工具

站点工具


侧边栏

博主公告

想读书,想旅游,想运动,但是没有时间?其实我们不是没有时间,只是没有真正把想做的事情,放在重要的位置上,或者干脆没时间搞清楚到底那件事情对你来说更重要。^_^ 欢迎大家收看《程序员带你学打羽毛球》 和博主一起加入运动的行列。 ease 11:53 - 08月02日




最新博文》更多博文

分类索引

博主简介
吕某某 Leo
河北人,网名:ease
资深IT菜鸟,创业者
兴趣爱好:
人工智能,运动,读书,coding
人生格言:
命由己造 相由心生 有容乃大 无欲则刚 》博主管理》关于博主


blog:ease:python:python协程coroutine图示

python 协程 coroutine 生产者-消费者模型图示

看了廖雪峰老师关于协程的教程,为了便于理解,用 axure 做了以下图示,对于初学者应该更容易理解一些:

  1. 函数是: A调用B B调用A,有统一的出入口。入口是参数,出口是 return 协程不同。
  2. 协程是:程序A执行过程中暂时中断,把CPU控制权交给 B ,B执行一段后,再切换回A ,A从中断的地方继续执行。
  3. 相比多线程,协程的优势:程序控制切换,不需要线程切换的开销,不需要锁机制,多cpu 多进程+协程可提供极高的并发性能。
  4. 协程的实现:Python对协程的支持是通过generator实现的。
  5. 在generator中,我们不但可以通过for循环来迭代,还可以不断调用next()函数获取由yield语句返回的下一个值。
  6. 但是Python的yield不但可以返回一个值,它还可以接收调用者发出的参数(通过gen.send())。
传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:

参考原文

参考代码:

def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'
 
def produce(c):
    c.send(None)
    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()
 
c = consumer()
produce(c)

图示:

  1. 注意到consumer函数是一个generator,把一个consumer传入produce后:
  2. 首先调用c.send(None)启动生成器;
  3. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;
  4. consumer通过yield拿到消息,处理,又通过yield把结果传回;
  5. produce拿到consumer处理的结果,继续生产下一条消息;
  6. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

blog/ease/python/python协程coroutine图示.txt · 最后更改: 03:42 - 09月02日 (外部编辑)