协程,又称微线程,纤程。协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈
协程能实现并发。
优点:
- 无需线程上下文切换的开销
- 无需考虑数据安全问题
- 方便切换控制留,简化编程模型
- 高并发,高扩展性,低成本
缺点:
- 无法利用多核资源,不能实现并行
- 只适用I/O操作密集型
yield 实现协程:
import time def consumer(): while True: n = yield #创建生成器函数,保存挂起和依据send传值继续该函数 if not n: return print('consumer--------consuming %s.....'%n) time.sleep(1) def producer(target): next(target) #初始化生成器函数 n = 0 while n < 5: n += 1 print('producer--------producing %s.....'%n) target.send(n) #传值 target.close() if __name__ == '__main__': producer(consumer()) '''producer--------producing 1..... consumer--------consuming 1..... producer--------producing 2..... consumer--------consuming 2..... producer--------producing 3..... consumer--------consuming 3..... producer--------producing 4..... consumer--------consuming 4..... producer--------producing 5..... consumer--------consuming 5.....'''
greenlet 模块实现协程
import greenlet def foo(): print('ok1') g2.switch() #switch 函数切换到g2对象 print('ok3') g2.switch() def bar(): print('ok2') g1.switch() print('ok4') g1 = greenlet.greenlet(foo) #创建greenlet 对象,传入需要执行对函数 g2 = greenlet.greenlet(bar) if __name__ == '__main__': g1.switch() #启动该函数
gevent 实现协程
import gevent,time def foo(): print('ok1') gevent.sleep(1) print('ok3') def bar(): print('ok2') gevent.sleep(2) #模拟I/O操作 print('ok4') g1 = gevent.spawn(foo) #创建gevent对象 g2 = gevent.spawn(bar) gevent.joinall([g1,g2]) #运行 '''ok1 ok2 ok3 ok4'''