atomics是javascript多线程原子操作api,必须与sharedarraybuffer配合在web worker中使用;需满足coep/coop响应头、crossorigin属性及http协议三条件才能启用,且仅支持sharedarraybuffer绑定的typedarray视图。

Atomics 不是 HTML 的功能,它属于 JavaScript 运行时能力,且必须搭配 SharedArrayBuffer 在多线程(如 Web Worker)中使用;纯 HTML 页面里直接写 Atomics.add() 会报 ReferenceError: Atomics is not defined 或 SharedArrayBuffer is not available。
为什么 Atomics.load() 一调就报错 “not available”
根本原因不是代码写错了,而是运行环境没达标。现代浏览器默认禁用 SharedArrayBuffer 和 Atomics,因为它们可被用于侧信道攻击(如 Spectre)。要启用,必须满足三项硬性条件:
- 服务端响应头包含:
Cross-Origin-Embedder-Policy: require-corp和Cross-Origin-Opener-Policy: same-origin -
<script></script>、<iframe></iframe>等跨域资源需显式加crossorigin属性,例如:<script crossorigin src="worker.js"></script> - 不能用
file://协议打开页面——本地开发必须走localhost或127.0.0.1,比如用npx serve启一个 HTTP 服务
缺任何一项,new SharedArrayBuffer(1024) 就会返回 undefined,后续所有 Atomics.* 调用必然失败。
SharedArrayBuffer + Int32Array 是唯一合法组合
Atomics 方法只接受类型化数组(TypedArray)视图,且该视图必须基于 SharedArrayBuffer 构建。对普通 Array、Uint8Array(非共享)、甚至 new Int32Array(new ArrayBuffer(1024)) 调用 Atomics.store() 都会抛出 TypeError: invalid argument type。
正确写法只有这一种链路:
const sab = new SharedArrayBuffer(4); // 4 字节,刚好放一个 int32 const arr = new Int32Array(sab); // 绑定视图 Atomics.store(arr, 0, 42); // ✅ 安全写入
注意:arr[0] = 42 这种普通赋值仍是**非原子的**,依然会引发竞态——必须全程使用 Atomics.* 方法访问。
Atomics.compareExchange() 是实现锁的核心,但别手写自旋锁
很多教程教用 Atomics.compareExchange(arr, 0, 0, 1) 模拟互斥锁(0=空闲,1=占用),逻辑没错,但实际踩坑极多:
- 主线程调用
Atomics.wait()会直接抛DOMException: wait not allowed on main thread,只能在 Worker 中用 -
Atomics.wait()必须套在while循环里检查条件,否则可能虚假唤醒(spurious wakeup) - 没有超时机制,一旦 notify 漏发,线程永久挂起
- 频繁 compareExchange 在高争用下导致 CPU 空转,性能反不如简单队列
真实项目中,优先考虑用 Atomics.wait()/Atomics.notify() 做生产者-消费者同步(比如共享缓冲区满/空信号),而不是模拟 mutex。
waitAsync() 是唯一能用在主线程的等待方式,但支持度有限
Atomics.waitAsync() 返回 Promise,允许主线程“不阻塞地等通知”,但它目前仅 Chromium 120+ 和 Firefox 125+ 支持,Safari 仍无计划。调用方式是:
Atomics.waitAsync(intArray, 0, 0).then(({async}) => {
if (async) console.log('被 notify 唤醒');
});
注意:它的第三个参数是“期望值”,和 wait() 一样,必须与当前 Atomics.load(intArray, 0) 一致才进入等待;不一致则立即 resolve。这个细节常被忽略,导致“等不到唤醒”。
真正难的从来不是怎么写那几行 Atomics.* 调用,而是设计好共享内存布局、明确线程间数据流转契约、并守住“所有访问必须经由 Atomics”的铁律——漏掉一次普通读写,整个原子性保证就崩了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











