python的协程,是一种协作(异步)工作方式;类似于多线程,但不是多线程,实际是在一个线程中工作;工作过程实际是利用协程模块(标准库asyncio),构建协程对象;当协程对象执行时,其中可以构造专属的等待方法,处于等待时,会调度其他的协程对象执行,当等待时间过后,又会恢复到原来的协程对象上来工作,类似于多线程的上下文切换,可以在使用维度上理解成微线程,特性如下:
1 2 3 4
| 协程是单线程异步的工作方式;能避免无意义的多线程切换;没有多线程的开销,因此能提升性能; 协程,没有多线程的锁机制,在一个线程中切换,因此效率会更高(性能); 协程不是多线程,不能利用cpu多核能力,不能实现并行,能实现并发; 必须自己来承担调度的责任(控制调度);
|
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import asyncio
async def say_hello(): print("Hello") await asyncio.sleep(1) print("World")
async def main(): await asyncio.gather(say_hello(),say_hello(),say_hello())
asyncio.run(main())
:>Hello :>Hello :>Hello //休眠1s :>World :>World :>World
|
第三方协程框架gevent
它封装了libevent事件循环的API,因此能自动切换io操作;但是语法上好像不够清晰,写起来像是同步操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import gevent
def say_hello(): print("Hello") print("World")
g1=gevent.spawn(say_hello) g2=gevent.spawn(say_hello) g3=gevent.spawn(say_hello)
g1.join() g2.join() g3.join()
:>Hello :>World :>Hello :>World :>Hello :>World
如需阻断,请查看备注代码
|
使用场景:
协程主要是为了允许在单线程中对 IO 密集的过程进行调度,它允许我们显式指定一个位置,程序可以从此处被挂起,转而执行其他任务,当 IO 结束时被调度,从当前位置返回然后处理结果。
总结:协程相对于多线程有明显的性能优势,因此在处理IO密集型操作时,一般使用协程而非多线程;但由于不能利用cpu多核,因此在处理计算密集型场景时,还是要优先考虑多进程/多进程+协程