当前位置:首页 > 技术 > 正文内容

浏览器如何实现共享内存以优化并发数据访问

访客 技术 2026年9月8日 18

在浏览器环境中,SharedArrayBuffer (SAB) 是实现跨执行上下文(如 Web Worker)高效数据共享的关键。它允许在多个线程间直接访问同一块物理内存,避免了传统 postMessage 带来的数据复制开销,特别适用于性能要求极高的场景。

1. 浏览器并发模型与通信挑战

JavaScript 在主线程中运行,为避免 UI 阻塞,浏览器引入了 Web Worker、SharedWorker、ServiceWorker 以及 WebAssembly 线程等并发机制。这些 Worker 拥有独立的内存空间,通常通过 postMessage 进行通信。然而,postMessage 的数据复制(结构化克隆)机制在处理大量或频繁传输的数据时,会严重影响性能。

2. SharedArrayBuffer 与 Atomics:共享内存的核心

2.1 SharedArrayBuffer (SAB)

SharedArrayBuffer 对象代表一块可被多个线程同时访问的二进制内存区域。当一个线程将 SAB 传递给另一个线程时,传递的是内存的引用,而非数据副本。这意味着在一个线程中对 SAB 的修改,会立即被其他访问该 SAB 的线程感知。

// 主线程
const sharedBuffer = new SharedArrayBuffer(1024); // 1KB 共享内存
const int32Array = new Int32Array(sharedBuffer);

const workerThread = new Worker("worker.js");
workerThread.postMessage(sharedBuffer); // 传递引用,实现共享
// worker.js
onmessage = (event) => {
  const sharedArray = new Int32Array(event.data);
  sharedArray[0] = 42; // 修改共享内存,主线程可见
};

2.2 Atomics 原子操作

由于多线程并发访问同一内存,为了防止数据竞争(race condition)和保证操作的原子性,浏览器提供了 Atomics 对象。它提供了一系列安全读写共享内存的方法,并支持构建同步原语,如锁、信号量等。

// 安全地存储数据
Atomics.store(int32Array, 0, 123);
// 安全地加载数据
const currentValue = Atomics.load(int32Array, 0);
// 原子地增加值
Atomics.add(int32Array, 1, 1);
// 等待特定条件(阻塞当前线程)
Atomics.wait(int32Array, 2, 0); // 在位置2等待值0
// 通知等待中的线程
Atomics.notify(int32Array, 2, 1); // 通知位置2上的一个等待线程

3. 共享内存的典型应用场景

  • 并行计算:将大型数据集(如图像、视频帧、AI 模型数据)放入 SAB,由多个 Worker 并行处理,充分利用多核 CPU 提升计算密集型任务的效率。
  • 实时数据同步:在游戏、音视频处理、实时通信等应用中,利用 SAB 实现低延迟的数据交换,如共享帧缓冲区、音频样本等。
  • WebAssembly 多线程:Wasm 线程可以直接使用 SAB 进行高效的内存共享,使得在浏览器中运行高性能计算库(如物理引擎、机器学习框架)成为可能。
  • 跨 Tab/Worker 数据缓存:同源的多个页面或 Worker 可以通过 SAB 共享大型对象,避免重复加载和复制,显著降低内存占用和加载时间。

4. 安全性要求:COOP/COEP 头部

为了防范 Spectre 等侧信道攻击,SharedArrayBuffer 的使用受到安全限制。要启用 SAB,网页必须设置特定的 HTTP 响应头:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
  

这两个头部(合称 COOP/COEP)确保了页面的隔离性和安全性。

5. 实际应用示例

应用领域 具体场景 关键技术
WebAssembly TensorFlow.js, OpenCV.js 的多线程版本 SharedArrayBuffer, Atomics
音视频处理 实时音频合成、视频帧缓冲共享 SharedArrayBuffer, AudioWorklet
游戏开发 物理引擎计算、AI 逻辑并行 SharedArrayBuffer, Worker 池
数据可视化 后台数据聚合与处理 SharedArrayBuffer, Web Worker
WebRTC 低延迟数据通道传输 SharedArrayBuffer, Atomics

6. 共享内存机制概览

  • SharedArrayBuffer:核心共享内存对象。
  • Atomics:提供线程安全的原子操作和同步工具。
  • 优点:数据无复制,性能高,延迟低。
  • 限制:需配置 COOP/COEP 安全头部。
  • 应用:并行计算、实时处理、AI、游戏等。

7. net::ERR_INSUFFICIENT_RESOURCES 错误解析

当浏览器报告 net::ERR_INSUFFICIENT_RESOURCES 错误时,通常意味着系统或浏览器内部的共享内存相关资源不足。这可能由以下原因引起:

  • 内存页粒度限制:现代操作系统以内存页(如 4KB)为单位分配共享内存。即使 SAB 很小,也至少占用一个内存页,并产生额外的内核对象和句柄。频繁创建大量小 SAB 会快速耗尽文件描述符或共享内存句柄的上限。
  • 同步原语资源耗尽:大量使用 Atomics.wait() / Atomics.notify() 会消耗浏览器内部的等待队列(类似 futex 机制)资源。
  • 安全隔离上下文限制:COOP/COEP 启用后,浏览器会严格管理共享内存的分配,当分配的共享内存句柄过多时,可能会主动拒绝新的分配请求。

7.1 典型触发场景

  • 创建数万个小尺寸(如 1KB)的 SAB。
  • Worker 线程中频繁地创建和销毁 SAB。
  • 在大量 SAB 上频繁执行 Atomics.wait/notify。
  • 浏览器处于低资源模式(如移动设备)。

7.2 优化建议

  • 内存复用:优先创建一个大的 SharedArrayBuffer,并在其上创建多个视图(如 Int32Array、Uint8Array),而不是创建大量小的 SAB。
  • 控制线程数量:过多的 Worker 线程会成倍增加资源消耗。
  • 避免短生命周期 SAB:设计时尽量复用共享内存,减少创建和销毁的频率。
  • 合理设置 SAB 尺寸:建议每个 SAB 至少 64KB,以减少内存页碎片。
  • 监控资源:使用浏览器提供的性能分析工具(如 chrome://tracing)来诊断内存分配问题。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。