协程
协程,又称微线程,纤程。英文名Coroutine。
协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。
通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定
协程和线程差异
在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。
协程对比 进程 线程
协程 用户层面的概念,是有用户通过代码自定义的。
进程 线程 都是操作系统层面的概念,有计算机自己实现。
简单实现协程
- 协程-yield
- 协程-greenlet
- 协程-gevent(重点)
先安装greenlet和gevent,使用pip install greenlet/gevent
协程-gevent(重点)代码实现
from gevent import monkey # 给程序打补丁,才能实现交替运行的协程 monkey.patch_all() # 破解的函数包括但不限于 recv recvfrom accept time.sleep() import gevent import time """默认情况下 协程是不能自动切换任务的 需要做一些措施-破解""" def worker(): for i in range(3): print("in worker %s" % gevent.getcurrent()) time.sleep(1) # 创建一个协程并且运行 协程执行函数 参数列表 g1 = gevent.spawn(worker) g2 = gevent.spawn(worker) g3 = gevent.spawn(worker) # time.sleep(10) # 通过这个验证spawn函数的时候 协程就已经执行了,此时这个等待10秒不起作用 # 保持主进程的存活 协程依赖于进程而存在 如果进程退出了 那协程就不存在了 # g1.join() # g2.join() # g3.join() # joinall阻塞等待所有的协程执行完成 参数就是协程列表 gevent.joinall([g1,g2,g3]) """ 如果创建协程 如何等待协程执行完成 如何破解使多任务可以自动切换 可以破解哪些函数 """
进程、线程、协程对比
- 进程是资源分配的单位
- 线程是操作系统调度的单位
- 进程切换需要的资源很最大,效率很低
- 线程切换需要的资源一般,效率一般
- 协程切换任务资源很小,效率高
- 多进程、多线程根据cpu核数不一样可能是并行的 也可能是并发的。协程的本质就是使用当前进程在不同的函数代码中切换执行,可以理解为并行。 协程是一个用户层面的概念,不同协程的模型实现可能是单线程 也可能是多线程。