什么是javascript中的共享数组缓冲区?_它如何实现多线程间的数据共享?

SharedArrayBuffer 是 JavaScript 中支持多线程共享内存的 ArrayBuffer,需配合 Atomics 实现原子操作以避免竞态;仅在跨域隔离(COOP+COEP)环境下可用,且必须通过 postMessage 传输并列入 transfer list。

共享数组缓冲区(SharedArrayBuffer) 是 JavaScript 中一种特殊的 ArrayBuffer,它允许多个执行上下文(比如主线程和 Web Worker)同时访问同一块内存区域,从而实现真正的多线程数据共享。

为什么需要 SharedArrayBuffer?

普通 ArrayBuffer 是“独占”的——一旦被某个视图(如 Int32Array)绑定,就无法被其他线程直接读写。而 SharedArrayBuffer 的底层内存是“可共享的”,配合 Atomics API,能安全地在多个 Worker 之间同步读写,避免竞态条件。

如何创建并跨线程共享?

基本流程如下:

  • 主线程创建 new SharedArrayBuffer(byteLength),例如 const sab = new SharedArrayBuffer(1024);
  • 将 sab 通过 postMessage(sab, [sab]) 传递给 Worker(注意必须显式列入 transfer list)
  • Worker 收到消息后,用相同类型视图(如 new Int32Array(sab))映射同一块内存
  • 双方现在操作的是物理地址一致的内存,修改会实时反映在对方视图中

如何安全地读写共享内存?

直接读写会导致竞争(如两个线程同时递增同一位置),必须用 Atomics 提供的原子操作:

  • Atomics.add(array, index, value) —— 原子加法,返回旧值
  • Atomics.load(array, index)Atomics.store(array, index, value) —— 安全读写
  • Atomics.wait(array, index, expectedValue, timeout) —— 配合 Atomics.notify() 实现线程等待/唤醒

这些操作保证不会被中断,是构建锁、计数器、信号量等同步原语的基础。

使用限制与注意事项

SharedArrayBuffer 并非随处可用:

  • 仅在支持 跨域隔离(Cross-Origin Isolation) 的上下文中启用(需设置 COOP: same-originCOEP: require-corp 响应头)
  • 出于安全考虑(防范幽灵/Spectre 类攻击),主流浏览器默认禁用,必须显式开启隔离环境
  • 不能直接序列化或克隆,只能通过 postMessage 传输,且必须在 transfer list 中声明

不复杂但容易忽略。