协程
协程是一种用户态的轻量级线程,又称微线程。
协程拥有自己的寄存器上下文和栈,调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
优点:
1.无需线程上下文切换的开销
2.无需原子操作锁定及同步的开销
3.方便切换控制流,简化编程模型
4.高并发+高扩展性+低成本:一个html" target="_blank">CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。
缺点:
1.无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
2.进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
使用Gevent
gevent是python的一个并发框架,以微线程greenlet为核心,使用了epoll事件监听机制以及诸多其他优化而变得高效.
•简单示例
gevent的sleep可以交出控制权,当我们在受限于网络或IO的函数中使用gevent,这些函数会被协作式的调度, gevent的真正能力会得到发挥。Gevent处理了所有的细节, 来保证你的网络库会在可能的时候,隐式交出greenlet上下文的执行权。
import gevent def foo(): print('running in foo') gevent.sleep(0) print('com back from bar in to foo') def bar(): print('running in bar') gevent.sleep(0) print('com back from foo in to bar') # 创建线程并行执行程序 gevent.joinall([ gevent.spawn(foo), gevent.spawn(bar), ])
执行结果
running in foo
running in bar
com back from bar in to foo
com back from foo in to bar
•同步异步
import random import gevent def task(pid): gevent.sleep(random.randint(0, 2) * 0.001) print('Task %s done' % pid) def synchronous(): for i in range(1, 10): task(i) def asynchronous(): threads = [gevent.spawn(task, i) for i in range(10)] gevent.joinall(threads) print('Synchronous:') synchronous() print('Asynchronous:') asynchronous()
执行输出
Synchronous:
Task 1 done
Task 2 done
Task 3 done
Task 4 done
Task 5 done
Task 6 done
Task 7 done
Task 8 done
Task 9 done
Asynchronous:
Task 1 done
Task 4 done
Task 5 done
Task 9 done
Task 6 done
Task 0 done
Task 2 done
Task 3 done
Task 7 done
Task 8 done
•以子类的方法使用协程
可以子类化Greenlet类,重载它的_run方法,类似多线线程和多进程模块
import gevent from gevent import Greenlet class Test(Greenlet): def __init__(self, message, n): Greenlet.__init__(self) self.message = message self.n = n def _run(self): print(self.message, 'start') gevent.sleep(self.n) print(self.message, 'end') tests = [ Test("hello", 3), Test("world", 2), ] for test in tests: test.start() # 启动 for test in tests: test.join() # 等待执行结束
•使用monkey patch修改系统标准库(自动切换协程)
当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。
由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成
import gevent import requests from gevent import monkey monkey.patch_socket() def task(url): r = requests.get(url) print('%s bytes received from %s' % (len(r.text), url)) gevent.joinall([ gevent.spawn(task, 'https://www.baidu.com/'), gevent.spawn(task, 'https://www.qq.com/'), gevent.spawn(task, 'https://www.jd.com/'), ])
执行输出
2443 bytes received from https://www.baidu.com/
108315 bytes received from https://www.jd.com/
231873 bytes received from https://www.qq.com/
可以看出3个网络操作是并发执行的,而且结束顺序不同
参考链接:http://hhkbp2.github.io/gevent-tutorial/
总结
以上所述是小编给大家介绍的python编程使用协程并发的优缺点,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
本文向大家介绍Python并发编程协程(Coroutine)之Gevent详解,包括了Python并发编程协程(Coroutine)之Gevent详解的使用技巧和注意事项,需要的朋友参考一下 Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporateroutine的缩写,直接翻译为协同的例
tornado.gen — Simplify asynchronous code Decorators Utility functions Legacy interface tornado.concurrent — Work with threads and futures Consumer methods Producer methods tornado.locks – Synchronizat
本文向大家介绍python并发编程之多进程、多线程、异步和协程详解,包括了python并发编程之多进程、多线程、异步和协程详解的使用技巧和注意事项,需要的朋友参考一下 最近学习python并发,于是对多进程、多线程、异步和协程做了个总结。 一、多线程 多线程就是允许一个进程内存在多个控制权,以便让多个函数同时处于激活状态,从而让多个函数的操作同时运行。即使是单CPU的计算机,也可以通过不停地在不同
本文向大家介绍Python中的并发编程实例,包括了Python中的并发编程实例的使用技巧和注意事项,需要的朋友参考一下 一、简介 我们将一个正在运行的程序称为进程。每个进程都有它自己的系统状态,包含内存状态、打开文件列表、追踪指令执行情况的程序指针以及一个保存局部变量的调用栈。通常情况下,一个进程依照一个单序列控制流顺序执行,这个控制流被称为该进程的主线程。在任何给定的时刻,一个程序只做一件事
本文向大家介绍python使用协程实现并发操作的方法详解,包括了python使用协程实现并发操作的方法详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python使用协程实现并发操作的方法。分享给大家供大家参考,具体如下: 协程 协程是一种用户态的轻量级线程,又称微线程。 协程拥有自己的寄存器上下文和栈,调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器
14.1.1 什么是协程 一个应用程序是运行在机器上的一个进程;进程是一个运行在自己内存地址空间里的独立执行体。一个进程由一个或多个操作系统线程组成,这些线程其实是共享同一个内存地址空间的一起工作的执行体。几乎所有'正式'的程序都是多线程的,以便让用户或计算机不必等待,或者能够同时服务多个请求(如 Web 服务器),或增加性能和吞吐量(例如,通过对不同的数据集并行执行代码)。一个并发程序可以在一个
本文向大家介绍使用Python中的greenlet包实现并发编程的入门教程,包括了使用Python中的greenlet包实现并发编程的入门教程的使用技巧和注意事项,需要的朋友参考一下 1 动机 greenlet 包是 Stackless 的副产品,其将微线程称为 “tasklet” 。tasklet运行在伪并发中,使用channel进行同步数据交换。 一个”greenlet”,是一个更加原始的
主要内容:面向读者,前提条件Java是一种多线程编程语言,我们可以使用Java来开发多线程程序。 多线程程序包含两个或多个可同时运行的部分,每个部分可以同时处理不同的任务,从而能更好地利用可用资源,特别是当您的计算机有多个CPU时。多线程使您能够写入多个活动,可以在同一程序中同时进行操作处理。 Java是最初由Sun Microsystems开发并于1995年发布的高级编程语言。Java运行在各种平台上,如Windows,M