Jesonhu/keep

20. JS 单线程运行机制,浏览器渲染机制 相关概念梳理

Opened this issue · 0 comments

资料整理,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正

大纲

  • 区分进程和线程
  • 浏览器是多进程的
  • 浏览器都包含哪些进程?
  • 浏览器多进程的优势
  • 重点是浏览器内核(渲染进程)
  • Browser进程和浏览器内核(Renderer进程)的通信过程
  • 梳理浏览器内核中线程之间的关系
  • GUI渲染线程与JS引擎线程互斥
  • JS阻塞页面加载
  • WebWorker,JS的多线程?
  • WebWorker与SharedWorker
  • 简单梳理下浏览器渲染流程
  • load事件与DOMContentLoaded事件的先后
  • css加载是否会阻塞dom树渲染?
  • 普通图层和复合图层
  • 从Event Loop谈JS的运行机制
  • 事件循环机制进一步补充
  • 单独说说定时器
  • setTimeout而不是setInterval
  • 事件循环进阶:macrotask与microtask

区分进程和线程

基本形象的比喻 原文

进程 是一个工厂,工厂有它的独立资源-工厂之间相互独立
线程 是工厂中的工人,多个工人协作完成任务-工厂内有一个或多个工人-工人之间共享空间

完善概念 (Tips: -> 相当于)

工厂的资源 -> 系统分配的内存(独立的一块内存)
工厂之间的相互独立 -> 进程之间相互独立
多个工人协作完成任务 -> 多个线程在进程中协作完成任务
工厂内有一个或多个工人 -> 一个进程由一个或多个线程组成
工人之间共享空间 -> 同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)

通过 windows 电脑的 任务管理器 可以更形象的理解:

进程是cpu资源分配的最小单位(系统会给它分配内存)

问题: 线程和进程的区别是什么?
答: 进程和线程都是一个时间段的描述,是CPU工作时间段的描述 (详情)
进程:上下文切换的程序执行时间总和= CPU加载上下文 + CPU执行 + CPU保存上下文

官方术语介绍:

  • 进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位)
  • 线程是cpu调度的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)

tips:

  • 不同进程之间也可以通信,不过代价较大
  • 现在,一般通用的叫法:单线程与多线程,都是指在一个进程内的单和多。(所以核心还是得属于一个进程才行)
  • js 执行是单线程 参考

浏览器是多进程的 原文

浏览器多进程的优势 原文

浏览器内核(渲染进程)原文

页面的渲染,JS的执行,事件的循环,都在这个进程内进行

请牢记,浏览器的渲染进程是多线程的(这点如果不理解,请回头看进程和线程的区分)

浏览器渲染进程(列举一些主要常驻线程):

  • GUI 渲染线程

    • 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
    • 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行
    • 注意,GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
  • JS引擎线程

    • 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
    • JS引擎线程负责解析Javascript脚本,运行代码。
    • JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序
    • 同样注意,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
  • 事件触发线程

    • 归属于浏览器而不是JS引擎,用来控制事件循环(可以理解,JS引擎自己都忙不过来,需要浏览器另开线程协助)
    • 当JS引擎执行代码块如setTimeOut时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件线程中
    • 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
    • 注意,由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)
  • 定时触发器线程

    • 传说中的setInterval与setTimeout所在线程
    • 浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)
    • 因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
    • 注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
  • 异步http请求线程

    • 在XMLHttpRequest在连接后是通过浏览器新开一个线程请求
    • 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。

来个图解理解下
image

参考资料