多任务——协程
一、协程
1.1 概念
协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。
通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定
1.2 实现方式
实现方式一:yield
import time
def custom():while 1:x = yield 0print("生成器执行%s"%x)def productor():g = custom()g.__next__()for i in range(1000):g.send(i)begin = time.time()
productor()
print(time.time()-begin)
实现方式二:
greenlet库:
是 Python 的一个第三方库(由 Stackless Python 项目衍生而来),用于实现微线程,也称为协程。与线程和进程不同,协程是用户态的轻量级线程,由程序自己控制调度,而不是由操作系统内核管理。
第一步:导入模块:(若没有先安装终端运行:pip3 install greenlet)
from greenlet import greenlet
第二步:手动实现协程切换
switch()
是greenlet
对象的方法,用于暂停当前协程的执行,并切换到另一个协程。
from greenlet import greenlet
import time
def study(name):print(f"{name}正在学习")time.sleep(1)g2.switch("赵六")print(f"{name}正在学习django")
def play(name):print(f"{name}正在玩apex")time.sleep(1)g1.switch("王五")print(f"{name}正在玩csgo")g1 = greenlet(study)
g2 = greenlet(play)
g1.switch("张三")
g2.switch("李四")
study
函数的name
参数始终是第一次调用时传入的值(即"张三"
),后续通过greenlet.switch()
传递的参数不会改变这个name
变量的值。这是理解greenlet
参数传递机制的关键。
输出结果:
张三正在学习
赵六正在玩apex
张三正在学习django
赵六正在玩csgo
关键对比:switch()
vs 函数调用
特性 | 函数调用 | greenlet.switch() |
---|---|---|
控制权转移方式 | 函数返回后恢复执行 | 手动通过switch() 切换 |
参数传递 | 调用时固定参数值 | 每次switch() 都可传递新参数 |
执行状态保存 | 仅保留调用栈 | 保存所有局部变量和执行位置 |
恢复位置 | 函数调用处的下一行 | 上次switch() 的下一行 |