浏览器进程与线程详解
进程与线程
进程
进程是 CPU 资源分配的最小单位。
多进程:多进程是指同一个时间里,同一个计算机系统允许多个进程处于运行状态。多进程可以在编代码的时候,同时听歌,且进程之间不会相互干扰。
线程
1.一个进程由一个或者多个线程组成,线程是一个进程中代码的不同执行路线。
2.进程相互独立,同一个进程下的各个线程共享程序的内存空间,包括代码段、数据集、堆等。
浏览器中的进程与线程
浏览器是多进程的

1.Browser 进程: 浏览器的主进程(负责协调、主控)
2.第三方插件进程: 每种类型的插件对应一个进程,仅当适用该插件时才创建。
3.GPU进程: 最多一个,用于 3D 绘制
4.浏览器渲染进程(内核): 默认每个 Tab 标签页面就是一个进程,互不影响,控制页面的渲染,脚本执行,事件处理等。
浏览器会优化:多个空白的 tab 标签会合并成一个进程。
多进程浏览器优点:
1.避免单个页面渲染影响整个浏览器
2.避免第三方插件影响整个浏览器
3.多进程利用了多核优势
4.方便沙盒模式
浏览器中的渲染进程 Renderer

浏览器中的渲染进程是多线程的
1.GUI 渲染线程
1.1 负责渲染浏览器界面,解析 HTML、CSS 构建 DOM树、CSSOM树
1.2 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行重新渲染。
2.JS 引擎线程
JS 内核,主要负责处理 JavaScript 脚本程序,例如 V8 引擎。
一个 tab 渲染进程只有一个 JS 线程运行,即 JS 引擎是单线程的。
JavaScript 是单线程的
JavaScript 为处理页面中用户的交互,以及操作DOM树、CSS样式树来给用户呈现一份动态而丰富的交互体验和服务器逻辑的交互处理。如果 JavaScript 是多线程的方式来操作这些 UI DOM,则可能出现 UI 操作的冲突。如果 Javascript 是多线程的话,在多线程的交互下,处于 UI 中的 DOM 节点就可能成为一个临界资源,假设存在两个线程同时操作一个 DOM,一个负责修改一个负责删除,那么这个时候就需要浏览器来裁决如何生效哪个线程的执行结果。当然我们可以通过锁来解决上面的问题。但为了避免因为引入了锁而带来更大的复杂性,Javascript在最初就选择了单线程执行。
GUI 渲染线程与 JS 引擎线程互斥。GUI 渲染线程优先级低于 JS 引擎线程。在 JS 引擎线程工作时会被挂起。
由于 GUI 渲染线程与 JavaScript 执行线程是互斥的关系,当浏览器在执行 JavaScript 程序的时候,GUI 渲染线程会被保存在一个队列中,直到 JS 程序执行完成,才会接着执行。因此如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉
3.事件触发线程
当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待 JS 引擎线程的处理。这些事件可以是当前执行的代码块如定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX 异步请求等,但由于 JS 的单线程关系所有这些事件都得排队等待 JS 引擎线程处理。
4.定时器线程
浏览器定时计数器并不是由 JavaScript 引擎线程计数的, 因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时是更为合理的方案。
5.网络请求线程
在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript 引擎的处理队列中等待处理。
Web workers
Web worker 是 JS 引擎线程向浏览器申请的一个子线程,解决单线程 JS 引擎进行密集型运算堵塞 GUI 渲染线程问题。
Service Worker 是基于 web worker 的一个独立线程,且加上了离线缓存的功能,详细的 service worker 介绍,可以看这篇。
浏览器渲染流程
用户请求 => Broswer 进程 => 渲染进程 Renderer => GUI 渲染线程,加载网页开始渲染(可能需要 GPU 进程协助, JS 引擎线程引起的回流 + 重绘) => Renderer 进程 => Broswer 进程
GUI 渲染线程渲染过程:

1.解析 html 建立 dom 树, 解析 css 建立 cssom 树
2.dom 树和 cssom 树组成 render 树
3.布局 render 树(Layout/reflow),负责各元素尺寸、位置的计算 (dom 的尺寸、位置的变化会引起 reflow)
4.绘制 render 树(paint),绘制页面像素信息 (样式变化会引起 repaint)
5.浏览器渲染
reflow 一定会引起 repaint, 但是 repaint 不一定会引起 reflow。