协程
和多线程比,协程有何优势?
最大的优势就是协程极高的执行效率。
1.因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
2.第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
代码1:
def consumer(): while True: number=yield#生成器 print('[CONSUMER] Consuming %s...' % num) consumer=consumer() next(consumer)#初始化执行到yield停止 for num in range(0,100): print('[PRODUCER] Producing %s...' % num) consumer.send(num)
结果:
[PRODUCER] Producing 0... [CONSUMER] Consuming 0... [PRODUCER] Producing 1... [CONSUMER] Consuming 1... [PRODUCER] Producing 2... [CONSUMER] Consuming 2... ...
解释:
1.代码中创建了一个叫做consumer的协程,并且在主线程中生产数据,协程中消费数据。
2.其中 yield 是python当中的语法。当协程执行到yield关键字时,会暂停在那一行,等到主线程调用send方法发送了数据,协程才会接到数据继续执行。
但是,yield让协程暂停,和线程的阻塞是有本质区别的。协程的暂停完全由程序控制,线程的阻塞状态是由操作系统内核来进行切换。
因此,协程的开销远远小于线程的开销。
代码2:
def consumer(): r = '' while True: n = yield r#由yield得到n的值,并且在执行完循环以后返回r,停在这个位置 if not n: return print('[CONSUMER] Consuming %s...' % n) r = '200 OK' def produce(c): c.send(None)#初始化,停在yield处 n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r=c.send(n)#由yield返回的结果 print('[PRODUCER] Consumer return: %s' % r) c.close() c = consumer() produce(c)
结果:
[PRODUCER] Producing 1... [CONSUMER] Consuming 1... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... [CONSUMER] Consuming 2... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... [CONSUMER] Consuming 3... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... [CONSUMER] Consuming 4... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... [CONSUMER] Consuming 5... [PRODUCER] Consumer return: 200 OK
解释:
- 首先调用
c.send(None)
启动生成器; - 然后,一旦生产了东西,通过
c.send(n)
切换到consumer
执行; consumer
通过yield
拿到消息,处理,又通过yield
把结果传回;produce
拿到consumer
处理的结果,继续生产下一条消息;produce
决定不生产了,通过c.close()
关闭consumer
,整个过程结束。