浏览器进程和线程

218 阅读5分钟

1. 进程(Process)

通俗解释:

  • 进程可以看作是一个正在运行的程序的实例。每个进程都有自己的内存空间、数据和资源。

  • 想象一下,进程就像是一个独立的办公室,里面有自己的桌子、文件和员工。每个办公室(进程)之间是相互隔离的,不能直接访问对方的文件。

在浏览器中的应用:

  • 浏览器通常会为每个打开的标签页创建一个独立的进程。这意味着每个标签页都在自己的“办公室”中运行,互不干扰。

  • 这种设计提高了安全性和稳定性:如果一个标签页崩溃,其他标签页仍然可以正常工作。

2. 线程(Thread)

通俗解释:

  • 线程是进程中的一个执行单元。一个进程可以包含多个线程,这些线程共享进程的资源(如内存)。

  • 想象一下,线程就像是办公室里的员工,他们共享同一张桌子和文件,但每个员工(线程)可以独立工作。

在浏览器中的应用:

  • 在浏览器中,主线程负责处理用户界面(UI)和事件(如点击、输入等)。

  • 其他线程(如 Web Worker)可以在后台执行任务,而不会阻塞主线程。这意味着用户界面可以保持响应,即使在执行复杂的计算时。

进程和线程之间的关系

  • 进程和进程之间隔离,一个进程崩溃不会影响其他进程

  • 一个进程可以并发多个线程,每个线程执行不同的任务

  • 进程与进程之间需要传递数据需要通过进程通信管道IPC传递

  • 共享内存空间:同一进程中的所有线程共享进程的地址空间,包括全局变量、堆内存等。

  • 一个进程中任意一个线程执行出错,会导致这个进程崩溃

所以js(线程)执行报错时导致整个渲染进程停止工作

  • 当一个进程关闭后,操作系统会回收该进程的内存空间

Chrome打开页面有哪些进程和线程

  • 浏览器进程:这是 Chrome 的主进程,负责管理用户界面、标签页、地址栏、书签等。所有的用户交互和浏览器的核心功能都在这个进程中运行。
  • 渲染进程:每个打开的标签页通常会有一个独立的渲染进程。渲染进程负责解析 HTML、CSS 和 JavaScript,渲染页面内容。这样做的好处是,如果一个标签页崩溃,其他标签页仍然可以正常工作。
  • GPU 进程:Chrome 还可能启动一个 GPU 进程,用于处理图形渲染和加速。
  • 扩展进程:如果您安装了 Chrome 扩展程序,每个扩展可能会在自己的进程中运行。这有助于提高安全性和稳定性。
  • 插件进程:如果您使用了 NPAPI 插件(如 Adobe Flash),这些插件通常会在单独的进程中运行。

如果后续打开新的标签页,浏览器进程和GPU进程是共享的,默认情况是为每个标签生成一个渲染进程,如果是同一站点的话,就共用一个渲染进程。

渲染进程中的线程

  • 主线程(Main Thread)

    • 负责处理DOM解析、样式计算、布局、绘制、JavaScript执行等核心任务。
    • 也处理用户输入事件(如点击、滚动)。
  • GUI渲染线程(GUI THread)

    • 负责渲染页面,解析html、css、构建DOM树、CSS树、render树、重排重绘
  • 合成线程(Compositor Thread)

    • 负责将页面分成多个图层(Layer),并合成最终图像。
    • 独立于主线程,提升滚动和动画的流畅性。
  • 光栅化线程(Raster Thread)

    • 将图层转换为位图(Rasterization),通常在GPU上执行。
    • 多个光栅化线程可并行处理不同图层的位图生成。
  • JavaScript引擎线程

    • 执行JavaScript代码,通常与主线程共享,但部分引擎支持多线程(如Web Worker)。
  • 定时器线程(Timer Thread)

    • 管理setTimeoutsetInterval等定时器,触发回调。
  • HTTP请求线程(Network Thread)

    • 处理网络请求,如XMLHttpRequest和Fetch API,通常与主线程分离。
  • Web Worker线程

    • 允许在后台运行JavaScript代码,独立于主线程,适合处理复杂计算。
  • Service Worker线程

    • 用于离线缓存和网络请求拦截,独立于主线程运行。

事件循环的工作流程

事件循环的核心是 任务队列(Task Queue)  和 微任务队列(Microtask Queue)

  1. 执行同步任务

    • 主线程执行当前调用栈中的同步任务(如 JavaScript 代码)。
  2. 检查微任务队列

    • 当调用栈为空时,主线程会检查微任务队列,依次执行所有微任务(如 Promise 的回调)。
  3. 渲染页面(如果需要)

    • 如果需要渲染页面(如样式计算、布局、绘制),主线程会执行渲染任务。
    • 渲染任务通常由合成线程和光栅化线程协助完成。
  4. 从任务队列中取出一个宏任务执行

    • 主线程从任务队列中取出一个宏任务(如 setTimeout 的回调)并执行。
    • 执行完宏任务后,再次检查微任务队列并执行所有微任务。
  5. 重复上述过程

    • 主线程不断循环上述过程,直到所有任务队列为空。