SharedArrayBuffer 配合 Atomics.or 可实现轻量、无锁的跨线程标志位同步,适用于 Worker 间快速通知状态就绪;通过 Int32Array 在 SharedArrayBuffer 上定义标志位容器,每位代表一个布尔状态,Atomics.or 原子设置特定位避免竞态。

SharedArrayBuffer 配合 Atomics.or 可以实现轻量、无锁的跨线程标志位同步,适用于 Worker 间快速通知某个状态已就绪(如“数据已加载完成”“初始化完毕”)。关键在于:SharedArrayBuffer 提供共享内存,Atomics.or 原子地设置特定位,避免竞态,且不阻塞线程。
准备共享标志位内存
需用 Int32Array 在 SharedArrayBuffer 上定义一个或多个 32 位整数作为标志位容器。每个整数可承载 32 个独立布尔标志(每位代表一个状态)。
例如,分配一个 4 字节缓冲区,映射为单元素 Int32Array:
const sab = new SharedArrayBuffer(4); const flags = new Int32Array(sab); // flags[0] 初始为 0,所有位均为 0(false)
在 Worker 中原子设置标志位
目标线程(如加载完资源的 Worker)调用 Atomics.or 设置某一位,例如第 5 位(bit index 5,对应掩码 1
const BIT_READY = 1
该操作是原子的,不会被其他线程中断,也无需加锁或等待。
主线程轮询检测标志位(无锁、非阻塞)
主线程不使用 Atomics.wait(避免阻塞),而是用 Atomics.load 轮询读取,并检查特定位是否置位:
function waitForReady() {
while ((Atomics.load(flags, 0) & BIT_READY) === 0) {
// 可选:短暂让出控制权,避免忙等耗尽 CPU
if (self.navigator?.userAgent) {
// 浏览器环境可用 setTimeout 模拟微延迟
await new Promise(r => setTimeout(r, 0));
}
}
console.log('Worker 已就绪');
}
- Atomics.load 确保读取最新值,不会因 CPU 缓存不一致而漏检
- 按位与(&)判断特定位是否为 1,比读整个值再比较更精确、高效
- 若需等待多个标志,可组合掩码,如 (val & (BIT_A | BIT_B)) === (BIT_A | BIT_B)
注意事项与边界情况
该方案简洁高效,但需注意:
- 必须启用跨域隔离:SharedArrayBuffer 在现代浏览器中仅在跨域隔离上下文(Cross-Origin-Opener-Policy + Cross-Origin-Embedder-Policy)中可用
- 不支持自动唤醒:Atomics.or 不会触发 Atomics.wait 的唤醒;若要用 wait/notify 模式,需搭配 Atomics.notify,但本例强调“无锁+异步”,轮询更直接可控
- 标志位不可自动清零:Atomics.or 只置位,不清零;如需双向通信(如“请求→响应→重置”),应额外使用 Atomics.and 或 Atomics.xor 清除位
- 避免误用数值运算:切勿对 flags[0] 直接赋值(flags[0] = x)或使用 ++/--,这会破坏原子性











