sharedarraybuffer + atomics.notify 必须在 worker 中调用,主线程调用会抛 typeerror;notify 仅唤醒同一索引、同一预期值上正执行 wait 的线程,需确保时序、视图类型(int32array)及值匹配,且 count 表示最大唤醒数而非固定数量。

SharedArrayBuffer + Atomics.notify 无法在主线程触发唤醒,必须在 Worker 中调用;且 notify 要生效,必须有另一线程正在同一视图、同一索引、同一预期值上执行 Atomics.wait。
Atomics.notify 只能在 Worker 中安全调用
主线程调用 Atomics.notify() 会直接抛出 TypeError: notify not allowed on main thread。这不是权限问题,而是浏览器硬性限制——主线程不允许阻塞或唤醒操作,避免 UI 冻结和调度不可控。
- 所有
Atomics.wait()和Atomics.notify()必须成对出现在 Worker 线程中 - 主线程如需“触发唤醒”,只能通过
postMessage通知某个 Worker,再由该 Worker 执行Atomics.notify() - 多个 Worker 可以共用同一
SharedArrayBuffer,但每个notify只唤醒等待在同一索引且值匹配的线程(不保证唤醒全部,可指定最大唤醒数)
notify 唤醒失败的三大常见原因
明明调了 Atomics.notify(view, index, count),但 wait 线程没反应——大概率是以下其一:
-
view不是Int32Array:传入Uint8Array或Float64Array会静默失败或报RangeError: view is not an Int32Array - 等待线程尚未进入
wait:notify发生在wait之前,消息丢失(无队列机制),必须确保时序:先wait,再notify - 索引位置值已变:比如
wait(view, 0, 1)要求view[0] === 1才挂起;若期间被其他线程改成 2,wait立即返回"not-equal",后续notify(view, 0)就找不到等待者
高频唤醒必须配合超时重试,不能依赖单次 notify
网络延迟、Worker 启动耗时、JS 执行抖动都会导致 wait → notify 时序错乱。高频场景(如每毫秒同步一次像素行)下,裸用 notify 极易漏唤醒。
- 在
wait侧加超时:用Atomics.wait(view, index, value, timeoutMs)(注意:timeout 参数在部分旧版浏览器被忽略,需降级兜底) - 在
notify侧主动轮询检查:比如每 5ms 检查一次Atomics.load(view, index) === expected,满足则notify,避免依赖单次信号 - 用
Atomics.compareExchange()配合状态位:例如把view[0]的低 16 位当计数器、高 16 位当版本号,每次变更都递增版本号,让wait等待特定版本,降低误唤醒概率
notify 的 count 参数不是“唤醒几个”,而是“最多唤醒几个等待者”
Atomics.notify(view, index, 1) 表示:最多唤醒 1 个正在 view[index] 上等待值为当前值的线程。它不广播,也不排队,更不补偿。
- 若 3 个 Worker 同时在
view[0]上wait(..., 1),而你只notify(view, 0, 1),仅 1 个会被唤醒,其余继续挂起 - 想唤醒全部?得传
Atomics.notify(view, 0, Infinity)或足够大的数(如100),但要注意:没有等待者时该调用无副作用,不会报错 - 不要用
count = 0试探是否有等待者——它什么都不做,无法用于状态探测
真正难的不是写对 notify,而是设计出能容忍唤醒丢失、时序偏移、多线程竞争的状态协议。一个 notify 调用背后,往往要搭配锁区管理、版本戳校验、超时退避和错误重入逻辑——这些才是高频唤醒能落地的关键。











