一文看懂Python中的协程
1. 什么是协程
在 Python 和 Lua 语言中,都有协程这个概念,那么什么是协程呢?
协程是单线程下的并发,又称微线程,纤程。英文名Coroutine。
一句话总结:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。
也就是说它和程序员有关系,相对线程和进程来说,调度是由CPU来决定调度的。
2. 协程出现的原因
Python 由于众所周知的 GIL 的原因,导致其线程无法发挥多核的并行计算能力。
在GIL之下,同一时刻只能有一个线程在运行,在多任务并发(非并行)的情况下,每个任务在合适的时候挂起(发起I/O)和恢复(I/O结束),这样可以极大的提高CPU的效率。
相对而言,如果是cpu密集型,推荐多进程的方式。
在早期的 Python 实现中,是通过 yield
和 send
来分别实现切换,及返回结果。
举例来说:
import random
import time
def stupid_fib(n):
index = 0
a = 0
b = 1
while index < n:
sleep_cnt = yield b
print('query https://www.xtuz.net {0} secs'.format(sleep_cnt))
time.sleep(sleep_cnt)
a, b = b, a + b
index += 1
print('-'*10 + 'test yield send' + '-'*10)
N = 20
sfib = stupid_fib(N)
fib_res = next(sfib)
while True:
print(fib_res)
try:
ss = random.uniform(0, 0.5)
print('ss=%s' %ss)
fib_res = sfib.send(ss)
except StopIteration:
break
yield
- 用来从子程序中断,并返回结果
send
- 用来从主程序向子程序发送信息
2. 协程的优缺点
协程优点主要有以下两点:
- 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
- 单线程内就可以实现并发的效果,最大限度地利用 CPU
协程缺点主要也有以下两点:
- 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
- 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
4. 协程的使用场景
协程基于generator,Python3 中内置了异步IO。遇到IO密集型的业务时,总是很费时间啦,多线程加上协程, 在磁盘在读写的同时,还能去做其他的事情,在WEB应用中效果尤为明显。
展开剩余53%