转自:http://blog.beginman.cn/blog/133/

协程概念

1.并发编程的种类:多进程,多线程,异步,协程

2.进程,线程,协程的概念区别:

进程、线程和协程的理解

进程:拥有自己独立的堆和栈,既不共享堆也不共享栈,进程由操作系统调度。

线程:线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。

协程:协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显式调度

3.协程:

协程可以认为是一种用户态的线程,与系统提供的线程不同点是,它需要主动让出CPU时间,而不是由系统进行调度,即控制权在程序员手上。

4.进程,线程,协程在python中的表现

关于进程,python有multiprocessing模块进行处理;关于线程,python的ThreadThreading处理;关于异步,有各种python框架如Tornado等调用linux下的select,poll,epoll等异步实现;关于协程,由yield来实现。

5.协程与yield

廖雪峰的python博客中学习总结协程如下:

1).子程序调用通过栈实现,一个线程执行一个子程序,有明确的执行顺序,而协程不同于此,协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。注意的一点是:如A,B两个子程序, A执行过程中可以去执行B,并不是调用B,B可以中断(挂起)转而回到A.

所以可以看到执行过程在A,B两个子程序中切换,但是A并没有调用B,B的中断可以通过yield来保存,A,B的执行过程像多线程,但是协程的特点在于一个线程执行

2).协程的优势:

最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

下面通过多线程的生产者消费者与协程的生产者消费者实例进行演示:

  1. # 多线程
  2. # coding=utf-8
  3. from threading import Thread
  4. from threading import Condition
  5. import time
  6. import random
  7. #为了达到理解效果,这里没有使用简便的Queue
  8. queue = []
  9. condition = Condition()
  10. MAX_LENGTH = 20
  11. #代码实例:http://blog.jobbole.com/52412/
  12. #生产者的工作是产生一块数据,放到buffer中,如此循环。
  13. #与此同时,消费者在消耗这些数据(例如从buffer中把它们移除),每次一块。
  14. #这里的关键词是“同时”。所以生产者和消费者是并发运行的,我们需要对生产者和消费者做线程分离。
  15. #这个为描述了两个共享固定大小缓冲队列的进程,即生产者和消费者。
  16. class ProducerThread(Thread):
  17. def run(self):
  18. nums = range(5)
  19. global queue
  20. while True:
  21. num = random.choice(nums)
  22. condition.acquire() # 锁定以生成数据
  23. if len(queue) == MAX_LENGTH:
  24. print u'队列已满,等待消费中...'
  25. condition.wait() # 线程等待
  26. queue.append(num) # 往队列中生成数据
  27. print "Produced", num
  28. condition.notify() # 通知线程等待的消费者消费数据
  29. condition.release() # 释放线程锁
  30. time.sleep(random.random())
  31. class ConsumerThread(Thread):
  32. def run(self):
  33. global queue
  34. while True:
  35. condition.acquire() #线程锁
  36. if not queue:
  37. print u"队列为空,等待生产者生成数据...."
  38. condition.wait() # 线程等待
  39. num = queue.pop(0) # 消费数据
  40. print "Consumed", num
  41. condition.notify() # 通知线程等待的生产者继续生成数据(生产者线程等待条件是队列已满)
  42. condition.release() # 释放线程锁
  43. time.sleep(2) #执行时间长点,让生产者生成更多数据来测试
  44. ProducerThread().start()
  45. ConsumerThread().start()

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。

下面改用协程的方式:

  1. # 协程
  2. #生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:
  3. def consumer():
  4. v = None
  5. while 1:
  6. m = yield v
  7. if not m:
  8. return
  9. print "[C]CLine:%s, CProduce:%s" % (m, v)
  10. v = 'range'
  11. def producter():
  12. i = 0
  13. c = consumer()
  14. c.next() # To avoid sending a non-None value to a just-started generator, you need to call next or send(None) first.
  15. while i < 5:
  16. try:
  17. i += 1
  18. print(u'[P]producing...%s' % i)
  19. v = c.send(i)
  20. print(u'[P]CReturn: %s' % v)
  21. except StopIteration:
  22. print 'Done!'
  23. break
  24. c.close()
  25. if __name__ == '__main__':
  26. producter()

执行结果如下:

  1. [P]producing...1
  2. [C]CLine:1, CProduce:None
  3. [P]CReturn: range
  4. [P]producing...2
  5. [C]CLine:2, CProduce:range
  6. [P]CReturn: range
  7. [P]producing...3
  8. [C]CLine:3, CProduce:range
  9. [P]CReturn: range
  10. [P]producing...4
  11. [C]CLine:4, CProduce:range
  12. [P]CReturn: range
  13. [P]producing...5
  14. [C]CLine:5, CProduce:range
  15. [P]CReturn: range

引用廖雪峰python协程的理解:

注意到consumer函数是一个generator(生成器),把一个consumer传入produce后:

首先调用c.next()启动生成器;

然后,一旦生产了东西,通过c.send(n)切换到consumer执行;

consumer通过yield拿到消息,处理,又通过yield把结果传回;

produce拿到consumer处理的结果,继续生产下一条消息;

produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

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

最后套用Donald Knuth的一句话总结协程的特点:

“子程序就是协程的一种特例。”

执行动态图如下:

下节要点:

1.Python异步与yield的总结

2.Tornado异步非阻塞实例与yield的总结


作者:BeginMan

网址: http://blog.beginman.cn/blog/133/

在未标明转载的情况下,本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

深入理解yield(二):yield与协程的更多相关文章

  1. 深入理解协程(二):yield from实现异步协程

    原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的第二篇. yield from ...

  2. yield与send实现协程操作

    yield与send实现协程操作 之前我们说过,在函数内部含有yield语句即称为生成器. 下面,我们来看看在函数内部含有yield语句达到的效果.首先,我们来看看以下代码: def foo(): w ...

  3. PHP下的异步尝试二:初识协程

    PHP下的异步尝试系列 如果你还不太了解PHP下的生成器,你可以根据下面目录翻阅 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunkify ...

  4. Kotlin Coroutine(协程): 二、初识协程

    @ 目录 前言 一.初识协程 1.runBlocking: 阻塞协程 2.launch: 创建协程 3.Job 4.coroutineScope 5.协程取消 6.协程超时 7.async 并行任务 ...

  5. yield、greenlet与协程gevent

    yield 在说明yield之前,我们了解python中一些概念. 在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(ge ...

  6. Python用yield form 实现异步协程爬虫

    很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习. 争取用看得懂的字来描述问题. 1.什么是yield 如果还没有怎么用过的话,直接把yield看做成一种特殊 ...

  7. PHP yield 分析,以及协程的实现,超详细版(上)

    参考资料 http://www.laruence.com/2015/05/28/3038.html http://php.net/manual/zh/class.generator.php http: ...

  8. python中和生成器协程相关的yield之最详最强解释,一看就懂(一)

    yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底 ...

  9. python协程--yield和yield from

    字典为动词“to yield”给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 next(...) 的 ...

  10. 再议Python协程——从yield到asyncio

    协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...

随机推荐

  1. 利用Teensy进行em410x卡模拟以及暴力破解em410x类门禁系统

    什么是低频?什么是EM410x? 首先,我不得不再次提一下那些工作在125khz频率下的低频卡(如:EM410X之类的),以便大家更好的阅读以下的内容. 什么是低频?以下就是低频的解释: 低频(LF, ...

  2. 解决在转发一条内容为满的彩信,删除主题FWD,发送的时候提示转化为短信。

    问题描述: 1.长按一条输入内容为满的彩信,选择转发 2.输入联系人-删除主题FWD-发送 测试结果为:提示正转化为短信(见附件) 预期结果为:不应该有提示,应该还是彩信 测试结果图为: 根据提示的T ...

  3. 转:sqlplus使用总结

    为什么我要使用sqlplus: SQLPLUS很多人用的并不多,在我观察周围来看,很多人都在使用PLSQL DEVELOPER,尤其是开发人员,更是如此,那学习SQLPLUS有啥好处呢?在我看来有如下 ...

  4. 一次delete基表回收DBA权限的危险性操作

    1.0事件还原:测试库某个对象,使用具有DBA角色用户导出,生产环境普通用户无法导入数据,因此需要回收测试库dba角色,revoke无法回收 2.0操作流程 回收角色报错 测试环境测试,delete删 ...

  5. 【linux基础】重命名文件和文件夹

    linux下重命名文件或文件夹的命令mv既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a目录移动到/b下,并重命名为c mv /a /b/c 其实在文本模式 ...

  6. HTML结构组成

    1. 文档的类型声明 <!doctype html> h5的声明方式 作用 : 告诉浏览器当前使用的HTML版本,以便浏览器能正确解析HTML标签和渲染样式 书写位置 : 文档最开始位置 ...

  7. stm32 看门狗配置

    1.独立看门狗: 1) 取消寄存器写保护(向 IWDG_KR 写入 0X5555) IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  //使能或者失能 2) ...

  8. 如何用移动硬盘安装win7 系统

    身边没有U盘和光盘,就只有一个移动硬盘.移动硬盘安装系统是怎么进行的.在这里小毛孩来给大家上一课. 前期准备: 1.移动硬盘. 2.win7 32位的操作系统(*.iso). 3.有系统且可开机的电脑 ...

  9. MySQL--Alter Table注意事项

    ======================================================================== ALTER TABLE 和FLUSH TABLE导致的 ...

  10. bat根据星期启动程序

    原来公司里的由于每次开机时启动的程序比较多,所以打算使用批处理程序,这里只列举了部分.在每周一到周五的时候,开机则启动指定的应用程序,如果是周末的两天则不启动任何程序,所以做了这个脚本.你如果需要,根 ...