sharedarraybuffer 是 html5 中实现主线程与 worker 间零拷贝共享内存的核心机制,需配合 atomics 同步、满足跨域隔离策略(coep/coop 响应头),并通过 transfer list 传递。

SharedArrayBuffer 允许主线程与 Worker(包括多个 Worker 之间)直接共享同一块内存,绕过 postMessage 的结构化克隆(即序列化/反序列化),从而实现零拷贝的高性能数据交换。但需注意跨线程读写同步问题,且现代浏览器默认禁用该特性(需显式开启跨域策略)。
启用 SharedArrayBuffer 的前提条件
由于 Spectre 安全漏洞影响,主流浏览器(Chrome 92+、Firefox 93+、Safari 15.4+)默认禁用 SharedArrayBuffer,必须满足以下任一条件才能使用:
- 页面运行在 安全上下文 中(即通过
https://或localhost加载); - 服务端响应头中包含
Cross-Origin-Embedder-Policy: require-corp和Cross-Origin-Opener-Policy: same-origin; - (仅限本地开发)Chrome 启动时添加标志:
--unsafely-treat-insecure-origin-as-secure="http://localhost:8080" --user-data-dir=/tmp/foo。
创建并传递 SharedArrayBuffer 到 Worker
不能直接通过 postMessage 传递普通 ArrayBuffer,必须是 SharedArrayBuffer 实例,并且需在 transferList 中显式声明(否则会复制而非共享):
// 主线程
const sab = new SharedArrayBuffer(1024 * 1024); // 1MB 共享内存
const int32View = new Int32Array(sab);
<p>// 写入初始值
int32View[0] = 42;</p><p>// 创建 Worker 并传入 SharedArrayBuffer(注意 transferList)
const worker = new Worker('worker.js');
worker.postMessage({ sab }, [sab]); // ✅ 关键:sab 必须出现在 transferList 中
</p>
Worker 中接收:
// worker.js
self.onmessage = function(e) {
const { sab } = e.data;
const int32View = new Int32Array(sab); // 直接基于 sab 构建视图
console.log(int32View[0]); // 输出 42 —— 与主线程共享同一内存
};
线程安全:使用 Atomics 进行同步读写
多个 Worker 或主线程同时读写同一位置会导致竞态。必须用 Atomics API 做原子操作或加锁:
-
Atomics.load(view, index)/Atomics.store(view, index, value):安全读写单个元素; -
Atomics.add(view, index, delta):原子加法(适合计数器); -
Atomics.wait(view, index, expectedValue, timeout)+Atomics.notify(view, index, count):实现阻塞等待与唤醒(类似条件变量); - 可组合实现自旋锁或更复杂的同步原语(如基于
Atomics.compareExchange的互斥锁)。
例如,Worker A 等待某个标志位变为 1,Worker B 设置它:
// Worker A(等待) const flag = new Int32Array(sab, 0, 1); Atomics.wait(flag, 0, 0); // 阻塞直到 flag[0] ≠ 0 <p>// Worker B(通知) flag[0] = 1; Atomics.notify(flag, 0, 1); // 唤醒最多 1 个等待者 </p>
典型适用场景与注意事项
SharedArrayBuffer 适合以下高吞吐、低延迟场景:
- 实时音视频处理(如 WebAssembly 模块与 JS Worker 协同处理帧数据);
- 多 Worker 并行计算大数组(如物理模拟、图像滤镜、矩阵运算);
- 高频传感器数据聚合(IMU、音频采样流);
⚠️ 注意事项:
- 不支持
ArrayBuffer.isView()检查 SharedArrayBuffer 视图(Int32Array(sab)是合法视图,但ArrayBuffer.isView()返回false); - 不能用于
JSON.stringify或structuredClone(会抛错); - 调试困难:Chrome DevTools 不显示 SharedArrayBuffer 内容(仅显示
[SharedArrayBuffer]); - 内存泄漏风险:只要任一线程持有对 SAB 的引用,内存就不会释放,需主动管理生命周期。
不复杂但容易忽略:始终检查 typeof SharedArrayBuffer === 'function' 并降级到 MessageChannel + Transferable ArrayBuffer(如 ImageBitmap、ArrayBuffer)作为备选方案。











