阅读视图

发现新文章,点击刷新页面。

JavaScript 中的二进制数据:ArrayBuffer 与 SharedArrayBuffer 全面解析

1. ArrayBuffer

  • 是什么:一段固定长度、连续的二进制内存。

  • 不能直接读写,必须通过视图(TypedArrayDataView)访问。

  • 常用场景

    • 文件读写(图片、音视频)
    • 网络传输(WebSocket、Fetch)
    • WebGL / GPU 数据
    • 加密解密数据
  • 示例

    const buf = new ArrayBuffer(4);
    const u8 = new Uint8Array(buf);
    u8[0] = 255;
    console.log(u8[0]); // 255
    

2. SharedArrayBuffer

  • 是什么:可以被多个线程同时访问的二进制内存。

  • 不会复制,跨线程传递时是零拷贝。

  • 需要配合 Atomics 保证数据同步。

  • 浏览器限制:需跨源隔离(COOP/COEP)。

  • 常用场景

    • 多线程数据共享(主线程 + Worker)
    • 实时游戏(物理计算 + 渲染)
    • 音视频解码与播放共享缓冲
    • 科学计算、机器学习
  • 示例

    const sab = new SharedArrayBuffer(4);
    const u32 = new Uint32Array(sab);
    u32[0] = 123;
    // 传给 Worker 后,两个线程可同时访问并修改
    

3. TypedArray

  • 是什么:定型数组视图,用固定类型访问 ArrayBuffer / SharedArrayBuffer

  • 特点

    • 高性能批量数值运算
    • 必须按类型大小对齐(如 Int32 按 4 字节)
    • 按系统字节序读写
  • 常用类型Uint8Array, Int16Array, Float32Array

  • 示例

    const arr = new Uint8Array([1, 2, 3]); // 自动分配底层 ArrayBuffer
    

4. DataView

  • 是什么:灵活的二进制视图,可按任意偏移读写各种类型,并指定字节序。

  • 特点

    • 不要求按类型大小对齐
    • 可选大端/小端序
    • 适合自定义二进制格式解析
  • 示例

    const buf = new ArrayBuffer(4);
    const dv = new DataView(buf);
    dv.setUint16(0, 65535, true); // 小端序
    console.log(dv.getUint16(0, true)); // 65535
    

5. 对比表

特性 ArrayBuffer SharedArrayBuffer TypedArray DataView
是否共享内存 ❌ 否 ✅ 是 依赖底层缓冲区 依赖底层缓冲区
跨线程传递 转移(原失效) 保留引用 依赖底层缓冲区 依赖底层缓冲区
类型 固定类型 任意类型
字节序控制 按系统字节序 ✅ 可指定
是否对齐 N/A N/A 必须对齐 不需要
常见用途 文件、网络、GPU 数据 多线程并发 数值计算 文件解析

ChatGPT Image 2025年8月12日 22_09_28.png

  • ArrayBuffer(蓝色块)

    • 位于中间,是原始二进制内存块,不能直接读写。
    • 需要通过视图(上方两个白色块)来访问。
  • TypedArray(左上白色块)

    • 一类固定类型、定长的数组视图(如 Uint8Array, Float32Array)。
    • 按系统字节序访问,速度快,适合批量数值计算。
    • 依赖底层的 ArrayBuffer 存储数据。
  • DataView(右上白色块)

    • 更通用的视图,可以按任意偏移读取各种类型,并指定大小端字节序。
    • 灵活度高,适合解析自定义二进制格式。
    • 也依赖底层的 ArrayBuffer
  • SharedArrayBuffer(下方蓝色块)

    • ArrayBuffer 类似,但可以在多个线程之间共享同一块内存(零拷贝)。
    • 需要配合 Atomics 来保证多线程数据安全。
    • 也能被 TypedArrayDataView 作为底层缓冲区使用。

📌 解读

  • ArrayBuffer / SharedArrayBuffer内存本体,负责存放原始数据。
  • TypedArray / DataView访问工具,决定如何解释和读写这块内存。
  • SharedArrayBuffer 可以理解为“多线程版 ArrayBuffer”,功能更强,但需要同步控制。

SharedArrayBuffer 使用限制及注意事项

SharedArrayBuffer 是 JavaScript 中用于在多个线程(如 Web Worker)间共享内存的底层对象,允许高效的并发数据访问。但它的使用受到多方面严格限制,主要出于安全和兼容性考虑:

  1. 跨源隔离要求(COOP + COEP)
    为防止安全漏洞(如 Spectre 侧信道攻击),现代浏览器要求页面必须开启跨源隔离才能启用 SharedArrayBuffer。
    具体来说,服务器必须设置以下 HTTP 响应头:

    • Cross-Origin-Opener-Policy: same-origin
    • Cross-Origin-Embedder-Policy: require-corp
      只有满足这两个条件,浏览器才允许页面访问 SharedArrayBuffer,否则会被禁用。
  2. 浏览器兼容性
    并非所有浏览器或版本都支持 SharedArrayBuffer。尤其是旧版浏览器或某些隐私模式下,可能完全禁用该功能。开发时应先检测是否支持。

  3. 固定大小且不可变
    SharedArrayBuffer 一旦创建,内存大小就固定了,无法动态扩展,使用时需要提前规划好内存大小。

  4. 必须通过视图访问
    SharedArrayBuffer 本身是底层原始内存块,不能直接读写,必须通过 TypedArray(如 Uint8Array)或 DataView 来访问。

  5. 多线程同步与安全
    由于 SharedArrayBuffer 允许多个线程共享内存,必须使用 Atomics 对象提供的原子操作来同步访问,避免竞态条件和数据损坏。

  6. 安全风险与性能考虑
    该技术虽高效,但使用不当容易引入竞态错误和安全隐患,建议仅在确有多线程共享内存需求且理解同步机制时使用。

❌