一文彻底理解JS线程为什么与GUI线程互斥

 更新时间:2025年08月19日 11:15:14   作者:当其无,  
JS引擎线程与GUI线程是严格互斥的,即JS引擎线程运行时,会挂起GUI线程,这篇文章主要介绍了JS线程为什么与GUI线程互斥的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在浏览器中,GUI 渲染线程(负责页面渲染和重绘)与 JS 引擎线程(负责执行 JavaScript 代码)的互斥性是由 DOM 操作的线程安全性浏览器的事件循环机制决定的。以下是详细解释:

1.根本原因:DOM 的线程不安全

  • DOM(文档对象模型) 是页面结构的核心表示,但 DOM 操作不是线程安全的。如果 GUI 渲染线程和 JS 引擎线程同时修改 DOM(例如 JS 删除一个元素,而渲染线程正在绘制该元素),会导致渲染结果不可预测甚至崩溃。
  • 浏览器的设计强制规定:JS 引擎线程执行时,GUI 渲染线程必须挂起,反之亦然。

2.事件循环(Event Loop)的调度机制

  • 浏览器通过 事件循环 协调任务的执行顺序,单次循环流程如下:
    1. JS 引擎线程:执行同步代码、微任务(如 Promise)。
    2. GUI 渲染线程:检查是否需要渲染(16.6ms/帧),执行重排(Reflow)、重绘(Repaint)。
    3. 宏任务队列:处理事件回调、定时器(setTimeout)、I/O 等。
  • JS 执行会阻塞渲染:如果 JS 引擎线程长时间占用(例如死循环),GUI 渲染线程会一直等待,导致页面“卡死”。

3.实际场景示例

  • 同步 JS 代码阻塞渲染

    <div id="box">Loading...</div>
    <script>
      // 长时间同步任务(模拟复杂计算)
      for (let i = 0; i < 1e9; i++) { /*...*/ }
      // 此时页面会卡在 "Loading...",无法渲染后续内容
      document.getElementById("box").innerHTML = "Done!";
    </script>
    
    • 用户会看到页面长时间无响应,直到 JS 执行完毕才会更新 UI。
  • 异步任务不阻塞渲染

    // 通过 setTimeout 将任务拆分为异步执行
    function updateText() {
      document.getElementById("box").innerHTML = "Done!";
    }
    setTimeout(updateText, 0);
    
    • GUI 渲染线程会在 JS 主线程空闲时更新页面。

4.优化策略

  • 避免长时间同步任务:将复杂计算拆分为异步任务(如 setTimeoutrequestIdleCallback)。
  • 使用 Web Workers:将耗时 JS 任务放到独立线程(Worker)中执行,不阻塞主线程。
  • 合理使用 requestAnimationFrame:在下一帧渲染前执行 JS 动画逻辑,确保与渲染同步。

5.例外情况:CSS 动画与 JS 的并行

  • 纯 CSS 动画(如 transformopacity)可通过 GPU 加速,不依赖 JS 引擎线程,因此即使 JS 执行,动画仍可能流畅运行。
  • JS 动画(如直接修改 lefttop)会触发重排/重绘,需依赖主线程,容易导致卡顿。

总结

线程职责互斥原因
JS 引擎线程执行 JavaScript 代码DOM 操作需要独占访问权
GUI 渲染线程页面渲染、重排、重绘防止渲染结果不一致或崩溃

通过理解这种互斥性,开发者可以更高效地优化页面性能,避免阻塞用户交互。

到此这篇关于JS线程为什么与GUI线程互斥的文章就介绍到这了,更多相关JS线程与GUI线程互斥内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • js编写简易的计算器

    js编写简易的计算器

    这篇文章主要为大家详细介绍了js编写简易的计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • JS 实现请求调度器

    JS 实现请求调度器

    这篇文章主要介绍了JS 实现请求调度器的方法,帮助大家更好的理解和学习使用js,感兴趣的朋友可以了解下
    2021-03-03
  • javascript实现点击提交按钮后显示loading的方法

    javascript实现点击提交按钮后显示loading的方法

    这篇文章主要介绍了javascript实现点击提交按钮后显示loading的方法,涉及javascript动态设置页面元素样式的相关技巧,需要的朋友可以参考下
    2015-07-07
  • Javascript中的this绑定介绍

    Javascript中的this绑定介绍

    在Javascript里,函数被调用的时候,除了接受声明是定义的形式参数,每一个函数还接受两个附加的参数:this和arguments。
    2011-09-09
  • JS前端图片最优化压缩方案

    JS前端图片最优化压缩方案

    这篇文章主要为大家介绍了JS前端图片最优化压缩方案,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • IE浏览器不支持getElementsByClassName的解决方法

    IE浏览器不支持getElementsByClassName的解决方法

    这篇文章主要介绍了IE浏览器不支持getElementsByClassName的解决方法,本文的方法比较完美的解决了这个问题,需要的朋友可以参考下
    2014-08-08
  • D3.js 从P元素的创建开始(显示可加载数据)

    D3.js 从P元素的创建开始(显示可加载数据)

    D3是一个基于数据操作的可视化js库,认识d3,就从最基础的显示可加载数据谈起,需要的朋友可以参考下
    2014-10-10
  • JS关闭子窗口并且刷新上一个窗口的实现示例

    JS关闭子窗口并且刷新上一个窗口的实现示例

    这篇文章主要介绍了JS关闭子窗口并且刷新上一个窗口的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • JavaScript 继承详解及示例代码

    JavaScript 继承详解及示例代码

    本文主要介绍JavaScript 继承的知识,这里整理了详细的资料及简单示例代码,帮助大家学习参考,有兴趣的小伙伴可以参考下
    2016-09-09
  • a标签click和href执行顺序探讨

    a标签click和href执行顺序探讨

    这篇文章主要介绍了a标签click和href执行顺序,需要的朋友可以参考下
    2014-06-06

最新评论