一、CPU
CPU是计算机的核心,其负责承担计算机的计算任务。这里我们比喻为一个工厂。
二、进程
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。
我们这里将进程比喻为工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。
三、线程
线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元。
这里把线程比喻一个车间的工人,即一个车间可以允许由多个工人协同完成一个任务。
四、进程和线程的区别和关系
- 进程是操作系统分配资源的最小单位,线程是程序执行的最小单位。
- 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
- 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号)。
- 调度和切换:线程上下文切换比进程上下文切换要
快得多
。
五、浏览器内核
浏览器内核是通过取得页面内容、整理信息(应用CSS)、计算和组合最终输出可视化的图像结果,通常也被称为渲染引擎。
Chrome浏览器为每个tab页面单独启用进程,因此每个tab网页都有由其独立的渲染引擎实例。
在浏览器中打开一个网页相当于新起了一个进程(进程内有自己的多线程)。
如果浏览器是单进程,那么某个Tab页崩溃了,就影响了整个浏览器,体验很差。同理如果是单进程,插件崩溃了也会影响整个浏览器。
六、浏览器的多线程
浏览器内核是多线程,在内核控制下各线程相互配合以保持同步,一个浏览器通常由以下常驻线程组成:
- GUI 渲染线程
- JavaScript引擎线程
- 事件触发线程
- 定时触发器线程
- 异步http请求线程
1.GUI渲染线程
GUI渲染线程
负责渲染浏览器界面HTML元素,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
当界面需要重绘(Repaint)或由于某种操作引发回流(重排)(reflow)时,该线程就会执行。
在Javascript引擎运行脚本期间,GUI渲染线程都是处于挂起状态的,也就是说被”冻结”了,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
2.JavaScript引擎线程
JavaScript引擎
,也可以称为JS内核,主要负责处理Javascript脚本程序,例如V8引擎。
JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序(单线程)。
注意⚠️:GUI渲染线程和JavaScript引擎线程互斥!
由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JavaScript线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。
因此为了防止渲染出现不可预期的结果,浏览器设置GUI渲染线程与JavaScript引擎为互斥的关系,当JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到引擎线程空闲时立即被执行。
如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
3.事件触发线程
当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。
这些事件可以是当前执行的代码块如定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。
4.定时触发器线程
setInterval
与setTimeout
所在线程
浏览器定时计数器并不是由JavaScript引擎计数的, 因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确。
通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
5.异步http请求线程
在XMLHttpRequest在连接后是通过浏览器新开一个线程请求。
将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中,再由JavaScript引擎执行。