不能直接用atomics.wait实现异步触发,它仅限worker线程且为同步阻塞调用;高频控制信号应采用原子轮询+notify轻量模式,依赖sharedarraybuffer跨域隔离前提与int32array视图,主线程store+notify,worker端load检测并清零。

不能直接用 Atomics.wait 实现“异步触发”——它本身是同步阻塞调用,且仅在 Worker 线程中合法。所谓“高频控制信号”,本质是低延迟、可重复、无竞态的状态通知机制,必须绕过 wait 的挂起语义,改用原子轮询 + notify 配合的轻量模式。
核心前提:确保跨域隔离与线程合法性
SharedArrayBuffer 和 Atomics.wait 要生效,页面必须满足跨域隔离:
- 服务端返回两个 HTTP 头:
Cross-Origin-Opener-Policy: same-origin和Cross-Origin-Embedder-Policy: require-corp - 本地开发必须走
http://localhost或 HTTPS,file://协议下new SharedArrayBuffer()直接抛错 -
Atomics.wait()只能在 Worker 线程中调用;主线程调用会立即报TypeError - 视图必须是
Int32Array,其他类型(如Uint8Array)会触发RangeError
高频信号 ≠ 频繁调用 wait,而是用 notify + 原子检查构建事件流
Atomics.wait(view, index, value) 不是定时器,它只在 view[index] === value 时挂起,否则立刻返回 "not-equal"。高频场景下反复调用 wait 会导致大量无效挂起与唤醒,开销反而更大。正确做法是:
- 主线程不 wait,只用
Atomics.store()写入信号值(如1表示“触发”),并紧接Atomics.notify(view, index, 1) - Worker 中用
Atomics.load()轮询检测变化,或在关键路径前加一次wait防忙等,但绝不循环 wait - 每次 notify 后,Worker 应立刻读取并重置标志位(如写回
0),避免漏信号或重复响应
典型高频控制信号模式(例如帧同步、采样开关)
假设共享内存前 4 字节为控制字,用于每毫秒级触发一次计算任务:
- 主线程(节奏控制器):
Atomics.store(controlView, 0, 1);<br>Atomics.notify(controlView, 0, 1);
- Worker(执行端):
收到通知后立即const sig = Atomics.load(controlView, 0);
若sig === 1,执行逻辑,然后Atomics.store(controlView, 0, 0)清零 - 不依赖 wait 的轮询备选(适合超短周期):
while (Atomics.load(controlView, 0) === 0) { /* 空转或 yield */ }
配合Atomics.compareExchange可避免伪唤醒
避坑要点:别把 wait 当信号接收器
常见错误写法及其后果:
-
Atomics.wait(controlView, 0, 0, 1)—— 第四参数毫秒被忽略,且若当前值已是1,调用直接返回"not-equal",根本没挂起 - 在主线程调用
wait—— 浏览器强制拒绝,无法调试 - 未配对
notify就调wait—— Worker 永久挂起,整个线程卡死 - 用
controlView[0] = 1替代Atomics.store—— 非原子写,可能被其他线程覆盖,信号丢失











