一文彻底理解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线程互斥内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Uniapp接入插件的3种方式总结

    Uniapp接入插件的3种方式总结

    我们在做uniapp的项目的时候经常需要用到各种插件,下面这篇文章主要给大家介绍了关于Uniapp接入插件的3种方式的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • js电话号码验证方法

    js电话号码验证方法

    JS电话号码验证是比较常的一种验证,下边给出一个JavaScript验证电话号码的小例子。国内固定电话都是七位或8位的数字组成的,还可以带有长途的区号。
    2015-09-09
  • ant design中实现table的表格行的拖拽

    ant design中实现table的表格行的拖拽

    这篇文章主要介绍了ant design中实现table的表格行的拖拽,文章围绕table表格行拖拽实现的相关资料展开详细的代码内容,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-03-03
  • JavaScript数组常用方法find、findIndex、filter、map、flatMap及some详解

    JavaScript数组常用方法find、findIndex、filter、map、flatMap及some详解

    在JavaScript中数组是一种非常常见且功能强大的数据结构,这篇文章主要介绍了JavaScript数组常用方法find、findIndex、filter、map、flatMap及some的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-07-07
  • 小程序实现轮播每次显示三条数据

    小程序实现轮播每次显示三条数据

    这篇文章主要为大家详细介绍了小程序实现轮播每次显示三条数据,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • js+canvas实现纸牌游戏

    js+canvas实现纸牌游戏

    这篇文章主要为大家详细介绍了js+canvas实现纸牌游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • html5+CSS 实现禁止IOS长按复制粘贴功能

    html5+CSS 实现禁止IOS长按复制粘贴功能

    因为在移动端APP需要实现长按执行别的事件,但是在iOS系统有默认的长按选择复制粘贴。禁止在网上找了很多资料,下面小编给大家分享解决方案,一起看看吧
    2016-12-12
  • JavaScript canvas实现动态点线效果

    JavaScript canvas实现动态点线效果

    这篇文章主要为大家详细介绍了JavaScript canvas实现动态点线效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • JS判断输入字符串长度实例代码(汉字算两个字符,字母数字算一个)

    JS判断输入字符串长度实例代码(汉字算两个字符,字母数字算一个)

    下面小编就为大家带来一篇JS判断输入字符串长度实例代码(汉字算两个字符,字母数字算一个)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • JavaScript实现登录滑块验证

    JavaScript实现登录滑块验证

    这篇文章主要为大家详细介绍了JavaScript实现登录滑块验证,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04

最新评论