最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何利用 SharedArrayBuffer 配合 Atomics 来构建极致性能的跨线程协作模型
时间:2026-07-26 10:39:49 编辑:袖梨 来源:一聚教程网
必须满足跨域隔离、正确同步、内存布局可控三项前提才能用SharedArrayBuffer和Atomics构建高性能跨线程模型;否则将引发静默数据错乱或TypeError。
不能直接用 SharedArrayBuffer 和 Atomics 构建“极致性能”的跨线程协作模型——除非你已满足跨域隔离、正确同步、内存布局可控这三项硬性前提。跳过任一环节,性能不会提升,只会引入静默数据错乱或 TypeError: SharedArrayBuffer is not defined。
SharedArrayBuffer 创建失败的常见报错和对应检查点
浏览器控制台报 SharedArrayBuffer is not defined 或 Atomics is not defined,不是代码写错了,而是环境没达标:
- 服务器响应头必须同时包含:
Cross-Origin-Opener-Policy: same-origin和Cross-Origin-Embedder-Policy: require-corp -
<script>、<iframe>、<link rel="stylesheet">等所有跨源资源加载标签需显式加crossorigin属性(哪怕同域) - 本地开发不能双击 HTML 文件打开(
file://协议被禁用),必须走localhost或127.0.0.1,例如npx serve -p 8080 - Chrome / Edge 105+、Firefox 93+、Safari 16.4+ 才完整支持;旧版 Safari 仅部分支持
Atomics.wait()
Atomics.wait() 不是 setTimeout,用错就卡死
Atomics.wait() 的行为常被误解为“让当前线程休眠 N 毫秒”,实际它只做一件事:在指定 Int32Array 索引位置的值**等于预期值**时,挂起当前线程,直到另一线程调用 Atomics.notify() 唤醒它。它不接受毫秒参数,也不保证唤醒时间。
- 错误写法:
Atomics.wait(view, 0, view[0], 1000)—— 第四个参数在多数浏览器中被忽略,且若view[0]已变,该调用立即返回"not-equal",根本不会等 - 正确模式:主线程写入
view[0] = 1→ Worker 检查Atomics.load(view, 0) === 1→ 调用Atomics.wait(view, 0, 1)→ 主线程后续调用Atomics.notify(view, 0, 1)唤醒 - 永远不要在无
notify配合的场景下单独使用wait,否则线程永久挂起,无法 debug
多线程计数器看似简单,但非原子操作必出错
以下两段代码执行 10000 次递增,在 4 个 Worker 并发下结果几乎必然不是 40000:
// ❌ 错误:非原子读-改-写int32View[0] = int32View[0] + 1;// ✅ 正确:单条原子指令完成Atomics.add(int32View, 0, 1);
- 前者拆成三步:读取 → 计算 → 写入,中间可能被其他线程打断,造成丢失更新(lost update)
-
Atomics.add()是 CPU 级原子指令映射,不可中断;类似地,Atomics.compareExchange()适合实现自旋锁 - 即使只读,也应优先用
Atomics.load(view, i)而非view[i],确保看到的是最新写入值(避免 CPU 缓存不一致)
WASM 多线程中 SharedArrayBuffer 的传递方式差异
在 WASM 场景下,SharedArrayBuffer 的使用路径和 JS Worker 不同,容易混淆:
- Emscripten 编译时必须加
-pthread -s USE_PTHREADS=1,否则生成的 WASM 模块根本不识别共享内存 - WASM 线性内存需声明为
(memory (shared 1 10)),即初始 1 页(64KB)、最大 10 页,且带shared标识 - JS 主线程传给 WASM Worker 的不是
SharedArrayBuffer对象本身,而是通过Module._malloc()分配的指针地址,由 WASM 自行映射到共享内存段 - WASM 内部调用
__atomic_add_fetch等内置函数,最终编译为对Atomics.add的调用,开发者无需手写 JS 层原子操作
最易被忽略的一点:共享内存没有自动垃圾回收机制。一旦创建 SharedArrayBuffer,它会一直驻留直到所有引用(包括 Worker 中的视图)全部释放。Worker 未正确 terminate() 或视图未置空,会导致内存泄漏,且无法被常规 DevTools 检测到。
相关文章
- 晴空双子500关通关阵容推荐 晴空双子传说级T0阵容搭配与实战解析 07-30
- 辉光之城1907好玩吗 辉光之城1907核心玩法与新手入门指南 07-30
- 未定事件簿主线第十八章行至黎明(上)即将开放 07-30
- 晴空双子爬塔阵容搭配指南 晴空双子高效率通关塔层阵容推荐 07-30
- 生存33天本周礼包码(1月12日) 07-30
- 原神月之四版本全新圣遗物介绍 07-30