不能靠Atomics.load单独实现高效轮询,必须搭配Atomics.wait/waitAsync与notify,并用compareExchange保障状态跃迁安全,且需满足COOP/COEP头、HTTPS环境、transfer list传递及统一视图等硬性前提。

不能靠 Atomics.load 单独实现“高效轮询”——它只是安全读取,不解决等待、唤醒或竞态问题。真正高效的状态同步,必须搭配 Atomics.wait(Worker 内)或 Atomics.waitAsync(Worker 内异步等待),并严格规避轮询逻辑。
为什么纯 load 轮询既低效又危险
轮询(比如 while (Atomics.load(view, 0) !== STATE_DONE) {})会持续占用 CPU,阻塞线程,且无法响应状态变化的精确时机。更关键的是:即使读到目标状态,也无法确认该状态是否已被其他线程覆盖或跳过——因为 load 本身不提供内存可见性保障以外的同步语义。
- 主线程改了状态,Worker 可能因缓存未刷新而读到旧值(
Atomics.load能保证可见性,但轮询节奏决定延迟) - 多个 Worker 同时轮询同一位置,无协作机制,易造成资源争抢或逻辑错乱
- 浏览器可能对密集轮询做节流,导致响应延迟不可控
正确做法:用 wait + notify 替代轮询
让 Worker 在状态未就绪时挂起,由状态变更方显式唤醒,这才是零开销、高响应的同步方式。前提是所有操作基于同一 SharedArrayBuffer 和一致视图。
- Worker 初始化后,先用
Atomics.load获取当前状态,判断是否需等待 - 若需等待,调用
Atomics.wait(view, 0, expectedValue)—— 它会原子地检查并挂起,直到值改变 - 状态变更方(如主线程或其他 Worker)执行
Atomics.store(view, 0, newValue)后,立即调用Atomics.notify(view, 0, 1) -
notify必须与wait的索引、视图类型(如都是Int32Array)、共享 buffer 完全一致
状态跃迁必须用 compareExchange 控制
仅靠 load 和 store 无法防止两个 Worker 同时从 IDLE 跳到 RUNNING。安全跃迁要靠条件写入:
- 定义常量:
const STATE_IDLE = 0, STATE_RUNNING = 1, STATE_DONE = 2 - 尝试切换:
const result = Atomics.compareExchange(view, 0, STATE_IDLE, STATE_RUNNING) - 若
result === STATE_IDLE,说明抢占成功;否则重试或放弃 - 所有状态读取统一用
Atomics.load(view, 0),禁止view[0]
跨 Worker 同步的硬性前提不能跳过
以下任一缺失,SharedArrayBuffer 创建即失败,Atomics 方法也会报错:
- 服务端必须返回两个响应头:
Cross-Origin-Opener-Policy: same-origin和Cross-Origin-Embedder-Policy: require-corp - 本地开发必须走
http://localhost或 HTTPS,file://协议直接禁用 - 传递
SharedArrayBuffer时,必须放入postMessage的 transfer list,例如:worker.postMessage({ sab }, [sab]) - 所有 Worker 必须用相同类型视图(如都用
new Int32Array(sab))映射同一块内存

















