协程(coroutine)可以理解为是线程的优化,又称之为轻量级进程。它是一种比线程更节省资源、效率更高的系统调度机制。
协程具有这样的特点,即在同时开启的多个任务中,一次只执行一个,只有当前任务遭遇阻塞,才会切换到下一个任务继续执行。这种机制可以实现多任务的同步,又能够成功地避免线程中使用锁的复杂性,简化了开发。
早先的协程是使用生成器关键字 yield 来实现的,代码特别复杂难懂。自从 Python 3.5之后,确定了协程的语法,使得创建协程的方式得到改善。Python 中,能够实现协程的模块有多个,如 asyncio、tornado 或 gevent。
这里以 asyncio 为例,先来了解一下创建协程所用到的概念:
下面通过代码演示最基本的协程用法:
# 导入asyncio模块
import asyncio
#定义协程处理函数
async def demo(x):
print(x)
r = await asyncio.sleep(1)
print(x,"again")
#生成协程对象,并传入 hello
coroutine = demo("城东书院")
loop = asyncio.get_event_loop()
try:
#将协程注册到实现事件循环对象中,并开始运行。
loop.run_until_complete(coroutine)
finally:
#程序结束关闭事件循环对象
loop.close()
运行结果为:
注意,以上程序代码只能用在 Python 3.5 以及后续版本。因为 async 和 await 关键字是 3.5 版本才新加入。并且,在 Python 3.7 版本及后续版本中,可以使用 asyncio.run(coroutine) 代替第10~16行的代码,它们是完全等价的。
上面的代码体现了实现协程的基本步骤:
与线程相比,协程封装的内容更多,实现起来更容易。
开发者使用协程会少考虑很多事情。在默认情况下应优先使用协程。但是有一个特点要注意,协程是多任务的顺序执行,只有当前任务挂起后,才会切换到其他任务来执行;而线程是以 CPU 轮换的方式执行。
因此,两者的运行机制有着本质上的区别,这使得二者都不可被代替。也就是说,如果业务需求要每个并行线程的处理进度也要同步,那么使用协程将不是一个很好的方案。在实际工作中,应根据业务需要来灵活运用线程或协程。