协程

协程是比线程更加微小的结构,称为Coroutine。一般的函数调用是通过栈实现的,一个线程就是执行一个函数,函数的调用总是一个入口,一个返回,调用顺序是明确的。而协程则不同,协程看上去也是函数,但在执行过程中在函数内部可以中断,转而执行其他的函数,在适当的时候在返回来继续执行。

协程的特点是在一个线程执行,其优势就是有极高的执行效率。因为函数切换不是线程切换,因此没有线程切换的开销,和多线程相比,线程数越多,协程的性能优势就越明显。此外,协程不需要线程锁的机制,因为只有一个线程,所以也不存在写变量冲突。

在利用多核CPU方面,可以采用多进程+协程的方式,充分利用多核并且发挥协程的高效率。Python对协程的支持是通过生成器实现的。

Python的yield不仅可以返回一个值,还可以接收调用者发出的参数。

以下示例使用生产者-消费者模式演示了协程的使用。

def consumer():
	r = ''
	while True:
		n = yield r
		if not n:
			return
		print('[CONSUMER] Consuming {}'.format(n))
		r = '200 ok'

def produce(c):
	c.send(None)
	n = 0
	while n < 5:
		n += 1
		print('[PORODUCER] Producing {}'.format(n))
		r = c.send(n)
		print('[PRODUCER] Consumer return {}'.format(r))
	c.close()

c = consumer()
produce(c)

这里需要注意以下几点:

  1. consumer是一个生成器,将其传入producer后,调用c.send(None)启动生成器;
  2. 一旦产生了内容,通过c.send(n)切换到consumer的执行;
  3. consumer通过yield拿到消息,处理后又通过yield传回结果;
  4. producer拿到consumer处理的结果,继续产生下一条消息;
  5. producer结束生产时,调用c.close()关闭consumer结束整个过程。

这整个运行过程中是不需要锁的,而且在同一个线程中执行。