V8引擎详解(九)——协程&生成器函数

前言

本文是V8引擎详解系列的第九篇,重点内容是关于生成器函数的运做机制,以及协程的概念。文末会有已经完成的系列文章的连接,本系列文章还在不断更新欢迎持续关注。javascript

生成器函数Generator

Javascript最初的规则中中,一个函数开始执行后,就会运行到最后或遇到return时结束,运行期间不会有其它代码可以打断它。而ES6中引入的Generator(生成器)函数打破了这个规则,Generator函数能够交出函数的执行权(暂停执行),这也是和普通函数最大的区别。
先说一下Generator的几个特色:html

  • 调用 Generator 函数,会返回一个内部指针(遍历器Iterator对象
  • 经过调用 遍历器Iterator对象 的next方法,遍历 Generator函数内部的每个状态
  • 建立时经过 在function关键字与函数名添加 "*" 用以和普通函数作区分
  • 函数体内经过多个 yield 表达式,定义不一样的内部状态,遍历器对象 使用next遍历时即返回当前的 yield 状态

经过一小段代码来看一下Generator函数java

function* gen() {
    yield 'first';
    yield 'second';
    yield 1 + 2;
    return 'end';
}

let g = gen();
g.next(); // {value: 'first', done: 'false'};
g.next(); // {value: 'second', done: 'false'};
g.next(); // {value: '3', done: 'false'};
g.next(); // {value: 'end', done: 'true'};
复制代码

用起来也很简单,经过构建函数 yiled 构建阶段状态,调用时经过调用next返回当前状态的信息(value)以及执行状态(done)。也正是经过Generator函数和Promise的结合完全解决了回调地狱的问题,并于ES7规范推出了官方语法糖async/await
本文主要来聊聊Generator函数究竟是如何实现的。缓存

进程与线程

想要了解协程就要先了解进程与线程的概念(这几个概念在计算机中都是属于比较抽象的概念也历来没有统一的标准定义,因此下面只表明我的的观点与理解)。bash

进程

  • 计算机的核心CPU承担全部的计算任务(先不说GPU)。
  • 操做系统管理计算机,负责任务的调度,资源的分配和管理。
  • 程序做用于操做系统,用来执行某种功能的集合。
  • 进程是为了实现程序的某种功能,对于某个数据集合的一次动态执行的过程。
  • 进程是操做系统进行资源分配和调度的一个独立单位(实体),也是操做系统执行的基本单元,程序是一个没有生命的实体,只有处理器赋予程序生命时(操做系统执行之),它才能成为一个活动的实体,咱们称其为进程

线程

进程最基本的能力就是 被操做系统调度 以及 进行资源分配和调度,做为一个调度资源的基本单位若是想要同一时间同时干两件事情,因而诞生了 线程 的概念。并发

线程经过如下特色来帮助进程能够在同一时间完成多件事情:async

  • 线程是程序执行的最小单位,而进程是操做系统分配资源的最小单位
  • 一个进程由一个或多个线程组成,线程是一个进程中代码的不一样执行路线
  • 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见
  • 线程上下文切换比进程上下文切换要快得多

以上即是进程和线程的基本概念,若是以为我说的仍是比较抽象,能够参考一下阮大大的进程与线程的一个简单解释来帮助理解。函数

协程和生成器函数

Generator函数 本质上就是协程的一种实现,若是你能理解协程是什么那么你就能轻松的理解Generator函数高并发

协程究竟是什么

协程是一种比线程更加轻量级的存在。你能够把协程当作是跑在线程上的任务,一个线程上能够存在多个协程,可是在线程上同时只能执行一个协程。post

协程概念的提出比较早,单核CPU场景中发展出来的概念,经过提供挂起和恢复接口,实如今单个CPU上交叉处理多个任务的并发功能。
那么本质上就是在一个线程的基础上,增长了不一样任务栈的切换,经过不一样任务栈的挂起和恢复,线程中进行交替运行的代码片断,实现并发的功能。(注意是并发不是并行)

协程的优点

  • 避免锁竞争

多个线程之间调用资源时会发生竞争关系,会致使锁的竞争,由于协程自己就是单核cpu上进行操做(在一个线程上同时只能执行一个协程),因此不存在竞争关系。

  • 协程消耗资源远比线程小

协程的每一个任务栈的占用的内存空间远比线程小,在高并发场景,线程太多也会致使OOM

  • 切换成本极低

协程的切换(挂起和恢复)彻底由用户控制,不须要系统进行切换,成本极低。

javascript中的协程

ES6中引入的生成器函数,就是给用户提供了协程特性的入口,经过生成器函数让咱们可使用协程的特性。
这些特性使得程序更适合高并发的I/O操做,更容易的真正解决了回调地狱的问题。

总结

本文主要了解了关于生成器函数的运做机制,以及协程的概念,若是你以前以为不够理解生成器函数,读完本文会发现其实本质上生成器函数不难理解,只要能够理解协程的概念,也就能明白为何会出现生成器函数。若是有什么错误,请在评论中和做者一块儿讨论,若是您以为本文对您有帮助请帮忙点个赞,感激涕零。

系列文章

V8引擎详解(一)——概述
V8引擎详解(二)——AST
V8引擎详解(三)——从字节码看V8的演变
V8引擎详解(四)——字节码是如何执行的
V8引擎详解(五)——内联缓存
V8引擎详解(六)——内存结构
V8引擎详解(七)——垃圾回收机制
V8引擎详解(八)——消息队列
V8引擎详解(九)——协程&生成器函数

相关文章
相关标签/搜索