A coroutine is a function that can suspend its execution (yield) until the given YieldInstruction finishes.算法
也就是说,协程是一个函数,能够被挂起和被恢复。编程
协程不是被操做系统内核所管理,而彻底是由程序所控制(也就是在用户态执行)。这样带来的好处就是性能获得了很大的提高,不会像线程那样须要上下文切换来消耗资源,所以协程的开销远远小于线程的开销。多线程
子程序,就是函数,在全部语言中都是层级调用,好比A调用B,B在执行过程当中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。函数
协程看上去也是子程序,但执行过程当中,在子程序内部可中断,而后转而执行别的子程序,在适当的时候再返回来接着执行。oop
注意,在一个子程序中中断,去执行其余子程序,不是函数调用,有点相似CPU的中断。好比子程序A、B:post
def A(): print '1' print '2' print '3' def B(): print 'x' print 'y' print 'z'
假设由协程执行,在执行A的过程当中,能够随时中断,去执行B,B也可能在执行过程当中中断再去执行A,结果多是:性能
1 2 x y 3 z
可是在A中是没有调用B的,因此协程的调用比函数调用理解起来要难一些。spa
看起来A、B的执行有点像多线程,但协程的特色在因而一个线程执行,那操作系统
和多线程比,协程有何优点?线程
1. 切换开销小,执行效率高
由于子程序切换不是线程切换,而是由程序自身控制
2. 不须要多线程的锁机制
由于只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只须要判断状态就行了
协程能够经过yield(取其“让步”之义而非“出产”)来调用其它协程,接下来的每次协程被调用时,从协程上次yield返回的位置接着执行,经过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的
1. 子程序能够调用其余子程序,调用者等待被调用者结束后继续执行,故而子程序的生命期遵循后进先出,即最后一个被调用的子例程最早结束返回。协程的生命期彻底由对它们的使用须要来决定。(也就是想怎么跳就怎么跳,不须要遵循函数调用那套规则)
2. 子程序的起始处是唯一的入口点,而协程能够有多个入口点,协程的起始处是第一个入口点,每一个yield返回出口点都是再次被调用执行时的入口点。
3. 子例程只在结束时一次性的返回所有结果值。协程能够在yield时不调用其余协程,而是每次返回一部分的结果值,这种协程常称为生成器或迭代器。
子例程是协程的特里,由于任何子例程均可以看做是不调用yield的协程
这里是一个简单的例子证实协程的实用性。
传统的生产者-消费者模型是一个线程写消息,一个线程取消息,经过锁机制控制队列和等待,但一不当心就可能死锁。
若是改用协程,生产者生产消息后,直接经过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:
var q := 新建队列 coroutine 生产者 loop while q 不满载 创建某些新产品 向 q 增长这些产品 yield 给消费者 coroutine 消费者 loop while q 不空载 从 q 移除某些产品 使用这些产品 yield 给生产者
根据今天查阅的资料来看,协程的应用场景主要在于 :I/O 密集型任务。