要实现 worker 与主线程强一致性数据同步,需通过 sharedarraybuffer + atomics 构建受控共享内存,配合 coep/coop 响应头、同源或 cors 合规、crossoriginisolated 为 true 等隔离前提,并严格使用 atomics api 进行原子读写。

要实现 Worker 线程与主线程的强一致性数据同步,关键不是“让两边同时写同一份数据”,而是通过 SharedArrayBuffer + Atomics 构建一个双方都信任、受控、可验证的共享内存区域,并用原子操作保证每一步读写都不可分割、顺序明确。它不靠锁排队,也不靠消息来回确认,而是靠硬件级原子指令达成纳秒级一致。
必须满足的隔离前提
浏览器会主动拦截不合规环境,缺一不可:
- 服务端响应头必须包含:
Cross-Origin-Embedder-Policy: require-corp和Cross-Origin-Opener-Policy: same-origin - 所有资源(HTML、JS、Worker 脚本)需同源,或带
crossorigin属性且服务端配好 CORS 头 - 不能用
file://打开页面;本地开发务必用npx serve或 Live Server 启 HTTP 服务 - 运行
self.crossOriginIsolated,返回true才能继续
共享内存的正确创建与分发
主线程是唯一创建者,Worker 只能复用视图,不能自己 new:
- 分配对齐内存:
const sab = new SharedArrayBuffer(8192)(推荐 4096 字节倍数) - 立即封装为 TypedArray:
const view = new Int32Array(sab),类型、字节偏移、长度必须在所有线程中完全一致 - 发送时必须显式 transfer:
worker.postMessage({ type: 'init', data: view }, [sab])—— 缺少[sab]就等于传了个null - 每个 Worker 都要单独发一次;transfer 出去的 sab 不可重用
所有访问必须走 Atomics API
普通数组语法(view[0] = x 或 view[0])会绕过原子保障,导致竞态,属于硬性错误:
- 写入统一用:
Atomics.store(view, index, value) - 读取统一用:
Atomics.load(view, index) - 增减计数器用:
Atomics.add(view, index, delta)(一步完成,天然无锁) - 条件更新必须用:
Atomics.compareExchange(view, index, expected, replacement),防止“读-判-写”中间被插队 - 等待状态变化(如等待 Worker 完成计算)用:
Atomics.wait(view, index, expectedValue)(仅 Worker 中可用)
结构化元数据协议(适用于 DOM 描述同步等场景)
SharedArrayBuffer 不能存对象,但可以高效承载结构化描述。例如同步元素位置与状态:
- 预定义定长结构体:每个描述符占 64 字节,字段按 offset 显式布局(如 id_hash 存于 bytes 4–7,x/y/w/h 各占 4 字节)
- 主线程写完一批数据后,递增版本号:
Atomics.add(view, 0, 1)(version 存在 index 0) - Worker 循环检查
Atomics.load(view, 0) !== lastVersion,变化则批量读取后续数据 - 写回结果时同样用 version + Atomics.store,主线程按新 version 拉取并批量更新真实 DOM
不复杂但容易忽略










