SharedArrayBuffer 与 Atomics 是 Worker 线程间高性能无锁同步的底层基石,需满足 crossOriginIsolated 环境、同源或 CORS 配置、显式 transfer、全部读写走 Atomics API,如 Atomics.add 和 Atomics.load,实现纳秒级强一致同步。

SharedArrayBuffer 与 Atomics 的组合,是实现 Worker 线程间高性能、无锁数据同步的底层基石。它不依赖消息序列化,避免拷贝开销,也不引入互斥锁的阻塞和调度开销,而是通过硬件级原子操作直接协调内存访问。
必须满足的运行前提
这套机制不是“写了就能跑”,浏览器会主动拦截未达标环境:
- 服务端必须返回两个关键响应头:Cross-Origin-Embedder-Policy: require-corp 和 Cross-Origin-Opener-Policy: same-origin
- 所有脚本(包括 Worker 文件)需同源,或带
crossorigin属性并配好 CORS 头 - 不能用
file://协议打开页面;本地开发请用npx serve或 VS Code Live Server 启 HTTP 服务 - 控制台执行
self.crossOriginIsolated,返回true才表示隔离生效
共享内存的创建与分发
主线程负责初始化共享内存,并确保每个 Worker 拿到的是同一块物理内存的引用,而非副本:
- 用
new SharedArrayBuffer(byteLength)分配内存(建议 4096 字节对齐,如 8192) - 立即用 TypedArray(如
Int32Array)包装,形成可操作视图 - 通过
postMessage(data, [sab])发送,transfer list 必须显式包含 sab,否则传输失败或得到 null - 若需多个 Worker 共享,主线程应分别向每个 Worker 调用
postMessage(..., [sab]),不可复用已 transfer 出去的 sab
用 Atomics 实现无锁协同
所有跨线程读写都必须绕过普通数组语法,全部走 Atomics API。这不是风格选择,而是安全红线:
- 写入:用
Atomics.store(view, index, value)替代view[index] = value - 读取:用
Atomics.load(view, index)替代view[index] - 计数器类场景:直接用
Atomics.add(view, index, delta),一步完成读-改-写,天然无锁 - 条件判断+更新:必须用
Atomics.compareExchange(view, index, expected, replacement),避免“读-判-写”中间被插队 - 等待与唤醒(如生产者-消费者):用
Atomics.wait(view, index, expectedValue)阻塞,配合Atomics.notify(view, index, count)唤醒,注意wait只能在 Worker 中调用,主线程调用会报错
典型无锁结构设计示例
以“多 Worker 并发更新一个整数计数器”为例,无需锁也能保证结果精确:
- 主线程分配
const sab = new SharedArrayBuffer(4),构建const counter = new Int32Array(sab),初始值设为 0 - 每个 Worker 收到 sab 后,同样用
new Int32Array(sab)构建视图(类型、偏移、长度必须完全一致) - Worker 内循环执行
Atomics.add(counter, 0, 1)—— 这一操作在 CPU 层面是原子的,不会丢失任何一次递增 - 主线程最终读取时,调用
Atomics.load(counter, 0)获取确定值
整个过程没有 lock、没有 wait、没有轮询,仅靠原子指令完成强一致性同步,延迟低至纳秒级。


















