sharedarraybuffer 实现多线程高性能内存同步的关键是安全访问与显式协同,需同时满足跨域隔离、atomics 原子操作及显式所有权转移三条件。

SharedArrayBuffer 能实现多线程间高性能原始内存同步,关键不在“分配内存”,而在于“安全访问”和“显式协同”。它本身不带同步能力,必须搭配 Atomics + 正确传递机制 + 跨域隔离环境,三者缺一不可。
必须启用跨域隔离(硬性前提)
现代浏览器默认禁用 SharedArrayBuffer,未满足安全策略时调用 new SharedArrayBuffer() 会静默失败或抛出 ReferenceError。需在主页面响应头中同时设置:
- Cross-Origin-Opener-Policy: same-origin
- Cross-Origin-Embedder-Policy: require-corp
HTML 中加载脚本、Worker 文件的 <script></script> 或 new Worker() 都需确保同源,或添加 crossorigin 属性。本地 file:// 协议下完全不可用,必须使用 http:// 或 https://(如 npx serve 启动本地服务)。
正确创建与转移共享内存
SharedArrayBuffer 是“裸内存”,不能直接读写,必须通过 TypedArray(如 Int32Array、Float64Array)绑定视图。且主线程创建后,必须用 postMessage(..., [sab]) 显式移交所有权,否则 Worker 收到的是 null 或拷贝失败:
- 主线程示例:
const sab = new SharedArrayBuffer(4096);<br>const view = new Int32Array(sab);<br>view[0] = 1; // 初始化<br>worker.postMessage({ buffer: sab }, [sab]); // ← transfer list 必须含 sab - Worker 内接收:
self.onmessage = ({ data }) => {<br> const { buffer } = data;<br> const view = new Int32Array(buffer); // 类型、长度需与主线程一致<br> console.log(Atomics.load(view, 0)); // → 1<br>};
所有读写必须走 Atomics(避免竞态)
普通数组操作(如 view[i] = x、view[i]++)在多线程下非原子,会导致撕裂读、丢失更新等静默错误。一切共享访问都应使用 Atomics 方法:
-
基础读写:用
Atomics.load(view, i)和Atomics.store(view, i, value)替代view[i] -
计数/累加:用
Atomics.add(view, i, delta)替代view[i] += delta -
条件等待:一个线程填完数据后,另一线程可
Atomics.wait(view, 0, 0)等待;填完方调用Atomics.notify(view, 0, 1)唤醒 -
比较交换:实现自定义锁或无锁结构时,用
Atomics.compareExchange(view, i, oldVal, newVal)
结构化布局与类型对齐(提升效率)
若需共享结构体(如含多个字段的帧数据),需手动规划内存偏移,例如:
- 前 4 字节存状态标志(
Int32Array索引 0) - 接下来 8 字节存时间戳(
Float64Array索引 1,需注意视图起始偏移) - 后续为图像像素(
Uint8Array从偏移 12 开始)
所有 Worker 和主线程必须使用完全一致的视图类型与偏移构造方式,否则读写错位。建议封装初始化函数统一管理布局,避免硬编码偏移值。











