无需登录 数据私有 本地保存

SharedArrayBuffer 通信演示 - 跨 Worker 共享内存

10
0
0
0
缓冲区使用
0/16
已用 / 容量
总写入次数
0
生产者
总读取次数
0
消费者
活跃 Worker
0
生产 + 消费
共享内存缓冲区
写指针: 0 读指针: 0 解锁
已填充 写指针 读指针
控制面板
暂无 Worker

快速慢速
实时操作日志
0 条
--:--:-- 系统就绪,等待操作...
常见问题与知识点

SharedArrayBuffer 是一种特殊的 ArrayBuffer,可以在多个线程(主线程和 Web Worker)之间共享同一块内存。这意味着多个线程可以同时读写同一块内存区域,无需通过 postMessage 复制数据,极大提升了通信效率,尤其适用于高性能计算、游戏引擎、音视频处理等场景。

与普通 ArrayBuffer 不同,SharedArrayBuffer 的内存是共享的,因此需要使用 Atomics API 来保证操作的原子性和线程安全。

当多个线程同时访问共享内存时,可能会出现竞态条件(Race Condition)。例如,两个线程同时读取同一个计数器、各自加1后写回,最终计数可能只增加了1而非2。

Atomics API 提供了原子操作(如 Atomics.add()Atomics.compareExchange()),保证操作不可分割。此外还提供:

  • Atomics.store() / Atomics.load() - 原子读写
  • Atomics.wait() - 在 Worker 中等待某个值变化(阻塞)
  • Atomics.notify() - 唤醒等待的线程
  • Atomics.compareExchange() - CAS 操作,实现无锁数据结构

出于安全考虑(Spectre 漏洞缓解),浏览器要求使用 SharedArrayBuffer 的页面必须处于跨域隔离环境。需要在服务器响应中设置以下 HTTP 头:

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

或使用更宽松的 credentialless 模式:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: credentialless

如果未设置这些头,typeof SharedArrayBuffer 将返回 'undefined',本工具会自动降级为模拟模式。

Atomics.wait()阻塞当前线程直到被通知或超时。如果在主线程中调用,会导致浏览器 UI 完全冻结,用户体验极差。因此浏览器禁止在主线程中使用 Atomics.wait(),仅允许在 Worker 线程中使用。

如果需要主线程等待共享内存变化,可以使用轮询 + Atomics.load() 配合 requestAnimationFramesetTimeout,或使用 Atomics.waitAsync()(较新的 API,返回 Promise)。

环形缓冲区(Circular Buffer / Ring Buffer)是一种固定大小的 FIFO 队列,使用两个指针管理读写:

  • 写指针(writeIndex):下一个要写入的位置
  • 读指针(readIndex):下一个要读取的位置

写入时,数据放入写指针位置,写指针前进;读取时,从读指针位置取数据,读指针前进。当指针到达数组末尾时,环绕回开头(取模运算)。

判断空/满:如果读写指针相等且计数为0则为空;如果计数等于容量则为满。在多线程环境中,计数器和指针的更新必须使用原子操作。

  • 音视频流处理:解码线程(生产者)将帧放入缓冲区,渲染线程(消费者)取出显示
  • 游戏引擎:物理计算线程产生位置数据,渲染线程消费
  • 日志系统:多个线程产生日志,单个线程负责写入文件
  • 网络数据包处理:接收线程写入数据包,处理线程读取解析
  • 数据库连接池:请求线程等待可用连接,使用后归还