从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理
前言
来源:https://dailc.github.io/2018/01/21/js_singlethread_eventloop.html
见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正。
———-超长文+多图预警,需要花费不少时间。———-
如果看完本文后,还对进程线程傻傻分不清,不清楚浏览器多进程、浏览器内核多线程、JS单线程、JS运行机制的区别。那么请回复我,一定是我写的还不够清晰,我来改。。。
———-正文开始———-
最近发现有不少介绍JS单线程运行机制的文章,但是发现很多都仅仅是介绍某一部分的知识,而且各个地方的说法还不统一,容易造成困惑。 因此准备梳理这块知识点,结合已有的认知,基于网上的大量参考资料, 从浏览器多进程到JS单线程,将JS引擎的运行机制系统的梳理一遍。
展现形式:由于是属于系统梳理型,就没有由浅入深了,而是从头到尾的梳理知识体系, 重点是将关键节点的知识点串联起来,而不是仅仅剖析某一部分知识。
内容是:从浏览器进程,再到浏览器内核运行,再到JS引擎单线程,再到JS事件循环机制,从头到尾系统的梳理一遍,摆脱碎片化,形成一个知识体系
目标是:看完这篇文章后,对浏览器多进程,JS单线程,JS事件循环机制这些都能有一定理解, 有一个知识体系骨架,而不是似懂非懂的感觉。
另外,本文适合有一定经验的前端人员,新手请规避,避免受到过多的概念冲击。可以先存起来,有了一定理解后再看,也可以分成多批次观看,避免过度疲劳。
大纲
区分进程和线程
浏览器是多进程的
浏览器都包含哪些进程?
浏览器多进程的优势
重点是浏览器内核(渲染进程)
Browser进程和浏览器内核(Renderer进程)的通信过程
梳理浏览器内核中线程之间的关系
GUI渲染线程与JS引擎线程互斥
JS阻塞页面加载
WebWorker,JS的多线程?
WebWorker与SharedWorker
简单梳理下浏览器渲染流程
load事件与DOMContentLoaded事件的先后
css加载是否会阻塞dom树渲染?
普通图层和复合图层
从Event Loop谈JS的运行机制
事件循环机制进一步补充
单独说说定时器
setTimeout而不是setInterval
事件循环进阶:macrotask与microtask
写在最后的话
区分进程和线程
线程和进程区分不清,是很多新手都会犯的错误,没有关系。这很正常。先看看下面这个形象的比喻:
- 进程是一个工厂,工厂有它的独立资源
- 工厂之间相互独立
- 线程是工厂中的工人,多个工人协作完成任务
- 工厂内有一个或多个工人
- 工人之间共享空间
再完善完善概念:
- 工厂的资源 -> 系统分配的内存(独立的一块内存)
- 工厂之间的相互独立 -> 进程之间相互独立
- 多个工人协作完成任务 -> 多个线程在进程中协作完成任务
- 工厂内有一个或多个工人 -> 一个进程由一个或多个线程组成
- 工人之间共享空间 -> 同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)
然后再巩固下:
如果是windows电脑中,可以打开任务管理器,可以看到有一个后台进程列表。对,那里就是查看进程的地方,而且可以看到每个进程的内存资源信息以及cpu占有率。

所以,应该更容易理解了:进程是cpu资源分配的最小单位(系统会给它分配内存)
最后,再用较为官方的术语描述一遍:
进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位)
线程是cpu调度的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)
tips
不同进程之间也可以通信,不过代价较大
现在,一般通用的叫法:单线程与多线程,都是指在一个进程内的单和多。(所以核心还是得属于一个进程才行)
浏览器是多进程的
理解了进程与线程了区别后,接下来对浏览器进行一定程度上的认识:(先看下简化理解)
浏览器是多进程的
浏览器之所以能够运行,是因为系统给它的进程分配了资源(cpu、内存)
简单点理解,每打开一个Tab页,就相当于创建了一个独立的浏览器进程。
关于以上几点的验证,请再第一张图:

图中打开了Chrome浏览器的多个标签页,然后可以在Chrome的任务管理器中看到有多个进程(分别是每一个Tab页面有一个独立的进程,以及一个主进程)。 感兴趣的可以自行尝试下,如果再多打开一个Tab页,进程正常会+1以上(不过,某些版本的ie却是单进程的)
注意:在这里浏览器应该也有自己的优化机制,有时候打开多个tab页后,可以在Chrome任务管理器中看到,有些进程被合并了 (所以每一个Tab标签对应一个进程并不一定是绝对的)
浏览器都包含哪些进程?
知道了浏览器是多进程后,再来看看它到底包含哪些进程:(为了简化理解,仅列举主要进程)
Browser进程:浏览器的主进程(负责协调、主控),只有一个。作用有
负责浏览器界面显示,与用户交互。如前进,后退等
负责各个页面的管理,创建和销毁其他进程
将Renderer进程得到的内存中的Bitmap,绘制到用户界面上
网络资源的管理,下载等
第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
GPU进程:最多一个,用于3D绘制等
浏览器渲染进程(浏览器内核)(Renderer进程,内部是多线程的):默认每个Tab页面一个进程,互不影响。主要作用为
- 页面渲染,脚本执行,事件处理等
强化记忆:在浏览器中打开一个网页相当于新起了一个进程(进程内有自己的多线程)
当然,浏览器有时会将多个进程合并(譬如打开多个空白标签页后,会发现多个空白标签页被合并成了一个进程),如图

另外,可以通过Chrome的更多工具 -> 任务管理器自行验证
浏览器多进程的优势
相比于单进程浏览器,多进程有如下优点:
避免单个page crash影响整个浏览器
避免第三方插件crash影响整个浏览器
多进程充分利用多核优势
方便使用沙盒模型隔离插件等进程,提高浏览器稳定性
简单点理解:如果浏览器是单进程,那么某个Tab页崩溃了,就影响了整个浏览器,体验有多差;同理如果是单进程,插件崩溃了也会影响整个浏览器;而且多进程还有其它的诸多优势。。。
当然,内存等资源消耗也会更大,有点空间换时间的意思。
重点是浏览器内核(渲染进程)
重点来了,我们可以看到,上面提到了这么多的进程,那么,对于普通的前端操作来说,最终要的是什么呢?答案是渲染进程
可以这样理解,页面的渲染,JS的执行,事件的循环,都在这个进程内进行。接下来重点分析这个进程
请牢记,浏览器的渲染进程是多线程的(这点如果不理解,请回头看进程和线程的区分)
终于到了线程这个概念了
从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理的更多相关文章
- js同步 异步 运行机制
需要知道的那些事: 1.JS是单线程的(为什么?因为能提高效率.作为浏览器脚本语言,js的主要用途是与用户互动,操作DOM.而这也就决定它只能为单线程,否则会带来很复杂的同步问题),也就是说无法同时执 ...
- Node.js和PHP运行机制对比
为什么要用node.js它又有什么优势呢?一个新的技术被大家喜爱那么它就必然有它的优势,那么下面我们就来简单把它和php做一个对比 1 . Node.js 他用的是JavaScript引擎,那么注定它 ...
- JS 冷知识,运行机制
数组取最小.最大值 var a=[1,2,3,5]; alert(Math.max.apply(null, a));//最大值 alert(Math.min.apply(null, a));//最小值 ...
- 【本周面试题】第2周 - js单线程和异步相关问题
硬性知识点考察: 为什么js是单线程的? 因为js设计最初是为了操作dom而生,如果是多线程的,当多个线程同时修改一个dom时就会产生冲突,所以设计成单线程,一次只能做一件事. 既然是单线程为什么要有 ...
- 从浏览器多进程到JS单线程,JS运行机制的一次系统梳理
前言 见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正. ----------超长文+多图预警,需要花费不少时间.---------- 如果看完本文后,还对进程线程傻傻分不清,不清楚浏 ...
- js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)
javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...
- js异步梳理:1.从浏览器的多进程到JS的单线程,理解JS运行机制
大家很早就知道JS是一门单线程的语言.但是也时不时的会看到进程这个词.首先简单区分下线程和进程的概念 1. 简单理解进程 - 进程是一个工厂,工厂有它的独立资源 - 工厂之间相互独立 - 线程是工厂中 ...
- 面试 09-02.js运行机制:异步和单线程
09-02.js运行机制:异步和单线程 #前言 面试时,关于同步和异步,可能会问以下问题: 同步和异步的区别是什么?分别举一个同步和异步的例子 一个关于 setTimeout 的笔试题 前端使用异步的 ...
- js为什么是单线程的?10分钟了解js引擎的执行机制
深入理解JS引擎的执行机制 1.JS为什么是单线程的? 为什么需要异步? 单线程又是如何实现异步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.说说setT ...
随机推荐
- 动态SQL之、条件判断(转)
错误方式一: 在mybatis的动态sql语句中使用<if>标签可以判断sql中的条件是否成立. <select id="getPerson" resultTyp ...
- uImage
linux内核经过编译后会生成一个ELF格式的可执行程序,叫vmlinux或vmlinuz,是原始的未经任何处理加工的原版内核ELF文件:嵌入式系统烧录的一般不是这个vmlinuz/vmlinux,而 ...
- maven转gradle ,windows错误重定向
gradle init --type pom --stacktrace > g.log 2>&1
- 第六节:WebApi的部署方式(自托管)
一. 简单说明 开篇就介绍过WebApi和MVC相比,其中优势之一就是WebApi可以不依赖于IIS部署,可以自托管,当然这里指的是 .Net FrameWork 下的 WebApi 和 MVC 相比 ...
- SpringBoot系列:Pojo validation
JSR 303 规范了bean validation, Hibernate validator实现了JSR 303所有的规范, 同时也是最常用的validator 工具包. 使用 Hibernate ...
- [再寄小读者之数学篇](2014-04-01 from 2103471050@qq.com 曲线积分)
求 $\int_\vGa y^2\rd s$, 其中 $\vGa$ 由 $\dps{\sedd{\ba{rl} x^2+y^2+z^2&=a^2\\ x+z&=a \ea}}$ 决定. ...
- python 写代码笔记 2017.6.15
其实并不是越复杂的代码越好,简单高效才是好. 关键是思路和逻辑,还有多看别人写的代码. 学习到了:)
- 校园wifi
我校师生访问本校校园WiFi(SSID为UESTC-WiFi),不受任何影响,用户名和密码均不变,可使用本校帐号加后缀@uestc.edu.cn,登录并免费使用eduroam联盟机构的WiFi(SSI ...
- python数据结构之堆(heap)
本篇学习内容为堆的性质.python实现插入与删除操作.堆复杂度表.python内置方法生成堆. 区分堆(heap)与栈(stack):堆与二叉树有关,像一堆金字塔型泥沙:而栈像一个直立垃圾桶,一列下 ...
- Linux 踩过的坑系列-01
关于默认网关的添加.记得楼主之前有一次,无意之间,也不知道做了什么删除文件里面内容的操作,配置好静态IP之后上不了外网.翻阅个各种资料都是没有找到问题.最后发现问题在于配置的虚拟机网卡文件的网关打错了 ...