简介

没有切换开销。因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高,

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

Python对协程的支持还非常有限,用在generator中的yield可以一定程度上实现协程。

yield

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

如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高

代码

importtimedefconsumer():

r= ''

whileTrue:

n= yieldrif notn:return

print('[CONSUMER] Consuming %s....' %n)

r= '200 OK'

defproduce(c):

c.next()

n=0while n < 5:

n= n + 1

print('[PRODUCER] Producing %s...' %n)

r=c.send(n)print('[PRODUCER] Consumer return: %s\n' %r)

c.close()if __name__=='__main__':

c=consumer()

produce(c)

结果

[PRODUCER] Producing 1...

[CONSUMER] Consuming1....

[PRODUCER] Consumerreturn: 200OK

[PRODUCER] Producing2...

[CONSUMER] Consuming2....

[PRODUCER] Consumerreturn: 200OK

[PRODUCER] Producing3...

[CONSUMER] Consuming3....

[PRODUCER] Consumerreturn: 200OK

[PRODUCER] Producing4...

[CONSUMER] Consuming4....

[PRODUCER] Consumerreturn: 200OK

[PRODUCER] Producing5...

[CONSUMER] Consuming5....

[PRODUCER] Consumerreturn: 200 OK

分析

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

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

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

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

整个过程无锁,由一个线程执行,producer和consumer写作完成任务,所以叫做协程

gevent

Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持

gevent是第三方库,通过greenlet实现协程,其基本思想是:

当一个greenlet遇到IO操作时(比如访问网络),就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

importgeventdeff(n):for i inrange(n):printgevent.getcurrent(), i

g1= gevent.spawn(f, 5)

g2= gevent.spawn(f, 5)

g3= gevent.spawn(f, 5)

g1.join()

g2.join()

g3.join()

结果

0 1

2

3

4

0 1

2

3

4

0 1

2

3

4

可以看出3个greenlet依次运行,而不是交替运行

要让greenlet交替运行,可以通过gevent.sleep()交出控制权

importgeventdeff(n):for i inrange(n):printgevent.getcurrent(), i

gevent.sleep(1)

g1= gevent.spawn(f, 3)

g2= gevent.spawn(f, 3)

g3= gevent.spawn(f, 3)

g1.join()

g2.join()

g3.join()

结果

000 1

1

1

2

2

2

可以看出3个greenlet是交替执行

如果把循环改为1000,让执行次数执行时间长些,查看进程,可以看到线程只有一个。

当然,实际代码中,不可能用gevent.sleep()去切换协程,而是在执行IO操作是,gevent自动切换,参考代码如下

importgeventfrom gevent importmonkey; monkey.patch_all()importurllib2deff(url):print 'GET: %s' %url

resp=urllib2.urlopen(url)

data=resp.read()print '[%d] bytes received from %s\n' %(len(data), url)

gevent.joinall([

gevent.spawn(f,'http://www.cnblogs.com/kaituorensheng/'),

gevent.spawn(f,'https://www.python.org/'),

gevent.spawn(f,'https://www.baidu.com'),

])

执行结果

GET: http://www.cnblogs.com/kaituorensheng/GET: https://www.python.org/GET: https://www.baidu.com

[227] bytes received from https://www.baidu.com

[14667] bytes received from http://www.cnblogs.com/kaituorensheng/[47348] bytes received from https://www.python.org/

可以看到3个url结束顺序并不是依次执行完的。

使用gevent,可以获得极高的并发性能,但gevent只能在Unix/Linux下运行,在Windows下不保证正常安装和运行。

由于gevent是基于IO切换的协程,所以最神奇的是,我们编写的Web App代码,不需要引入gevent的包,也不需要改任何代码,仅仅在部署的时候,用一个支持gevent的WSGI服务器,立刻就获得了数倍的性能提升。

python携程gevent_python gevent 协程相关推荐

  1. Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)

    一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 1 简单的启动线程语法 2 def run(na ...

  2. python gevent 协程

    python gevent 协程 def func1():print("fun1开始运行")gevent.sleep(2) # 内部函数实现io操作print("func ...

  3. python 协程库_python --- 协程编程(第三方库gevent的使用)

    1. 什么是协程? 协程(coroutine),又称微线程.协程不是线程也不是进程,它的上下文关系切换不是由CPU控制,一个协程由当前任务切换到其他任务由当前任务来控制.一个线程可以包含多个协程,对于 ...

  4. python携程多核_python 协程

    最近对Python中的协程挺感兴趣,这里记录对协程的个人理解. 要理解协程,首先需要知道生成器是什么.生成器其实就是不断产出值的函数,只不过在函数中需要使用yield这一个关键词将值产出.下面来看一个 ...

  5. python 协程和异步的关系_python协程与异步协程

    在前面几个博客中我们一一对应解决了消费者消费的速度跟不上生产者,浪费我们大量的时间去等待的问题,在这里,针对业务逻辑比较耗时间的问题,我们还有除了多进程之外更优的解决方式,那就是协程和异步协程.在引入 ...

  6. Python—进程、线程、协程

    一.线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 方法: ...

  7. python gil协程_GIL以及协程

    GIL以及协程 一.GIL全局解释器锁 演示 ''' python解释器: - Cpython c语言 - Jpython java 1.GIL:全局解释器锁 - 翻译:在同一个进程下开启的多个线程, ...

  8. python 协程库_python协程概念

    什么是协程 协程是单线程下的并发,又称微线程,纤程.它是实现多任务的另一种方式,只不过是比线程更小的执行单元.因为它自带CPU的上下文,这样只要在合适的时机,我们可以把一个协程切换到另一个协程.英文名 ...

  9. python 协程_Python 协程与 Go 协程的区别(一)

    ? "Python猫" ,一个值得加星标的公众号 花下猫语:年关将近,不知各位过得怎样?我最近有些忙,收获也挺多,以后有机会分享下.吃饭时间,追了两部剧<了不起的麦瑟尔夫人& ...

最新文章

  1. 【C语言】 strstr查找子字符串函数以及模拟实现讲解
  2. python读取指定字节长度的文本
  3. 2019运维技能风向标
  4. 推荐 7 个 Vue2、Vue3 源码解密分析的开源项目
  5. 程序员必知的8大排序(三)-------冒泡排序,快速排序(java实现) .
  6. (原創) 如何对array或struct做初始化? (memset()) (C/C++) (C)
  7. tableview的顶部有一部分空白区域,并不是Cell的解决方法。
  8. 99+好友共同关注,公众号推荐
  9. MSCI发布最新ESG评级 三七互娱位居A股游戏行业最高
  10. 微信公众帐号开发教程第11篇-符号表情的发送(上)
  11. python爬虫怎么赚钱-如何用爬虫技术赚钱?
  12. statspack report分析
  13. matlab调用第三方api_matlab与外部程序接口调用心得(原创)
  14. MySQL统计每月数量并计算同比增长率
  15. java 生成树形_Java实现生成Excel树形表头完整代码示例
  16. 保研复习笔记:概率论与数理统计
  17. java fmail发送邮件_【已实测通过】JavaMail常用的几种邮件发送方式
  18. 汽车研发企业试验数据管理系统建设研究
  19. PHP根据字符串拼音首字母进行排序/PHP通讯录按字母A-Z排序
  20. 43份ChatGTP报告分享

热门文章

  1. 2019年18种最有效推广的方式
  2. 如何将多个excel文件合并成一个
  3. 英文版Ubuntu16.04安装fcitx-googlepinyin
  4. S32Kxxx bootloader之CAN bootloader
  5. 爱尔兰哨笛教程(瑞恩牧师)
  6. 织梦DEDE自带采集标题限制,解决文章标题字数长度方法
  7. 动画舞蹈html5,纯CSS3动画:一棵跳舞的树
  8. 电脑无法识别u盘是怎么回事?数据能恢复吗
  9. linux字体技术原理
  10. 《跟着小吴哥学python》之 09 python中的编译与反编译