要理解generator就必须知道一个概念,那就是协程
。javascript
协程,又成为微线程(coroutine)。html
进程(process) vs 线程(thread)java
咱们都知道在操做系统级别上有两个重要的概念(也是实体):进程(process)和线程(thread),这两个东西是用于操做系统模拟并行
的,在单个CPU上,os经过调度算法,让CPU轮流执行线程或者进程,来达到程序的并发执行。node
那么协程又是什么?首先要明确的是,协程是编译器级别的,而并不是线程和进程同样是操做系统级别的。协程的实现,经过是对某个语言作相应的提议,而后经过后成编译器标准,而后编译厂商来实现该机制。git
协程的做用是什么?github
简单来讲,就是实现函数的分段式执行。就是一个函数的执行能够主动放弃CPU的控制权,先挂起,让其余的函数先执行,而后在返回,从上次执行结束的地方继续执行。算法
这样看起来很像是多线程轮流执行。可是却有着很大的区别:协程是一个线程执行
。编程
由于是一个线程执行,因此不存在线程的切换,而是由程序自身控制,也就不存在所谓的线程切换的开销。安全
不须要多线程的锁机制。由于只有一个线程,也就不存在同时写变量的冲突。在协程中控制共享资源不加锁,只须要判断状态就行了。这也说明协程的执行效率很高一些。网络
举个生产者消费者模型基于抢占式多线程编程
的实现(伪代码)
// 资源,队列容器 var q = []; // 消费者进程 loop(); // 循环等待 lock(q); // 加锁 var item = getResourceFrom(q); // 获取资源 unlock(q); // 操做结束,资源解锁 operatingResource(item); sleep; // 生成者线程 loop(); // 循环等待 var item = createResource(p); // 生产资源 lock(q); // 加锁 q.push(item); // 写入资源 unlock(q); // 解锁
能够看到,以上的代码中有两个特色
对资源操做须要进行加锁和解锁的操做。(保证线程安全)
消费者线程必须经过sleep,让出CPU,用于执行生产者线程使用。
那么若是是协程的编程模式,就简单地多。
var q = []; var count = 0; // 消费者 function *consumer() { while (true){ var item = yield producer(); console.log(item); } } // 生产者 function producer() { q.push(count++); } function main () { const consumerGen = consumer(); // 咱们能够经过代码来控制其交替执行 // 执行到获取item以前,放弃执行权,先执行producer(), consumerGen.next(); // 以后能够获取item,而后再放弃执行权,执行producer,一直循环 consumerGen.next(q.shift()); // 0 consumerGen.next(q.shift()); // 1 consumerGen.next(q.shift()); // 2 consumerGen.next(q.shift()); // 3 consumerGen.next(q.shift()); // 4 consumerGen.next(q.shift()); // 5 } main();