协程(coroutine),又称为微线程,纤程。(协程是一种用户态的轻量级线程
作用:在执行A 函数的时候,可以随时中断,去执行B 函数,然后中断继续执行A 函数(可以自动切换),注意这 一过程并不是函数调用(没有调用语句),过程很像多线程,然而协程只有一个线程在执行
对于单线程下,我们不可避免程序中出现io 操作,但如果我们能在自己的程序中(即用户程序级别,而非操作系统 级别)控制单线程下的多个任务能在一个任务遇到io 阻塞时就将寄存器上下文和栈保存到其他地方,切换到另外一 个任务去计算。在任务切回来的时候,恢复先前保存的寄存器上下文和栈,这样就保证了该线程能够最大限度地处 于就绪态,即随时都可以被cpu 执行的状态,相当于我们在用户程序级别将自己的io 操作最大限度地隐藏起来,从 而可以迷惑操作系统,让其看到:该线程好像是一直在计算,io 比较少,从而更多的将cpu的执行权限分配给我们 的线程(注意:线程是CPU 控制的,而协程是程序自身控制的)
协程的标准:
必须在只有一个单线程里实现并发
1.修改共享数据不需加锁
2.用户程序里自己保存多个控制流的上下文栈
3.一个协程遇到IO 操作自动切换到其他协程
由于自身带有上下文和栈,无需线程上下文切换的开销,属于程序级别的切换,操作系统完全感知不到,因而更加轻 量级;无需原子操作的锁定及同步的开销;方便切换控制流,简化编程模型,单线程内就可以实现并发的效果,最 大限度地利用cpu,且可扩展性高,成本低(注:一个CPU 支持上万的协程都不是问题。所以很适合用于高并发处 理)
他的缺点:无法利用多核资源:协程的本质是个单线程,它不能同时将单个CPU 的多个核用上,协程需要和进程配合 才能运行在多CPU 上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu 密集型应用。进行阻塞 (Blocking)操作(如IO 时)会阻塞掉整个程序
from greenlet import greenlet #导入协程模块 #开发协程的案例 1.回答 2.问问题 def ask(name): print("%s:我要买个包"%name) b.switch("吕布") #answer函数第一次切换需要传参 print("%s:我想喝奶茶" % name) b.switch() def answer(name): print("%s:买 买 买"%name) a.switch() print("%s:喝 喝 喝"%name) if __name__ == '__main__': a=greenlet(ask) #通过一个函数名字创建一个协程 b=greenlet(answer) #创建第二一协程 a.switch('貂蝉') #每个函数只有在第一次切换的时候才需要传参 后面不需要
简单的说就是进程下有线程 线程下有协程
在阻塞等待时 CPU切换到正在工作的协程 从而最大限度的利用CPU
只能在单线程下使用