Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。

SharedArrayBuffer

BaselineWidely available *

SharedArrayBuffer 对象用来表示一个通用的原始二进制数据缓冲区,类似于ArrayBuffer 对象,但它可以用来在共享内存上创建视图。与可转移的ArrayBuffer 不同,SharedArrayBuffer 不是可转移对象

描述

要在集群中的一个代理(agent,可以是网页的主程序或其任意一个 web worker)与另一个代理之间使用ShareArrayBuffer 共享内存,需要使用postMessage结构化克隆

结构化克隆算法接受SharedArrayBuffer 对象和映射到SharedArrayBuffer 对象的类型化数组。在这两种情况下,SharedArrayBuffer 对象会被传输给接收者,从而在接收代理中产生一个新的、私有的SharedArrayBuffer 对象(就像ArrayBuffer 一样)。但是,两个SharedArrayBuffer 对象指向的共享数据块其实是同一个数据块,一个代理中对数据块的修改最终会将在另一个代理中可见。

js
const sab = new SharedArrayBuffer(1024);worker.postMessage(sab);

共享内存可以被 worker 线程或主线程创建和同时更新。根据系统(CPU、操作系统、浏览器)的不同,需要一段时间才能将变化传递给所有上下文环境。因此需要通过原子操作来进行同步。

SharedArrayBuffer 被一些 web API 使用,比如:

安全需求

由于幽灵漏洞,共享内存和高精度定时器在 2018 年 1 月 5 日开始被禁用。在 2020 年,一种新的、安全的方法已经被标准化,以重新启用共享内存。

作为基本要求,你的文档需要处于一个安全上下文中。

对于顶级文档,需要设置两个标头来实现你网站的跨源隔离:

http
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp

为了验证跨源隔离是否生效,你可以测试窗口和 worker 上下文中的Window.crossOriginIsolatedWorkerGlobalScope.crossOriginIsolated 属性:

js
const myWorker = new Worker("worker.js");if (crossOriginIsolated) {  const buffer = new SharedArrayBuffer(16);  myWorker.postMessage(buffer);} else {  const buffer = new ArrayBuffer(16);  myWorker.postMessage(buffer);}

在设置了这两个标头后,postMessage() 不再为SharedArrayBuffer 对象抛出错误,因此,跨线程共享内存现在可用。

嵌套文档和专用 worker 线程也需要将Cross-Origin-Embedder-Policy 标头设置为同样的值。对于同源嵌套文档和子资源,不需要进行任何其他更改。同站(但跨源)嵌套文档和子资源需要将Cross-Origin-Resource-Policy 标头设置为same-site。而它们的跨源(和跨站点)的对应部分也需要将同样的标头设置为cross-origin。请注意,将Cross-Origin-Resource-Policy 标头设置为除same-origin 之外的任何值,都会使资源暴露于潜在的攻击中,比如幽灵漏洞

请注意,Cross-Origin-Opener-Policy 标头会限制你对弹出窗口引用的保留能力。两个顶级窗口上下文之间的直接访问基本上只在它们同源且携带相同的两个标头(且具有相同的值)时才可行。

API 可用性

根据是否采取了上述安全措施,各类内存共享 API 具有不同的可用性:

  • Atomics 对象总是可用的。
  • SharedArrayBuffer 对象在原则上始终可用,但遗憾的是,除非设置了前面提到的两个标头,否则其在全局对象上的构造函数是隐藏的,这是为了兼容 web 内容。这个限制有望在未来被移除。尽管如此,仍然可以用WebAssembly.Memory 来获取实例。
  • 除非设置了上文提到的两个标头,否则各种postMessage() 的 API 在处理SharedArrayBuffer 对象时会抛出异常。如果正确设置了这两个标头,Window 对象和专用 worker 线程上的postMessage() 都可以正常工作,并允许跨线程共享内存。

WebAssembly 共享内存

WebAssembly.Memory 对象可以通过设置shared 构造函数标志来创建。当这个标志设置为true 时,构造出的Memory 对象就像SharedArrayBuffer 一样,可以通过postMessage() 在 worker 线程之间共享,而且Memory 对象的后备buffer 是一个SharedArrayBuffer。因此,上述关于在 worker 线程间共享 SharedArrayBuffer 的要求同样适用于共享WebAssembly.Memory

WebAssembly Thread 提案还定义了一套新的原子指令。就像SharedArrayBuffer 及其方法始终可用(并且只有在设置了新标头的情况下,才允许线程间共享)一样,WebAssembly 原子指令也是始终可用的。

增大 SharedArrayBuffer

SharedArrayBuffer 对象可以通过在调用SharedArrayBuffer() 时包含maxByteLength 选项来使其可增大。你可以通过访问SharedArrayBuffergrowablemaxByteLength 属性来分别查询其是否可增大以及其最大大小。你还可以通过调用grow() 为一个可增大的SharedArrayBuffer 分配新的大小。新字节被初始化为 0。

这些特性令增大SharedArrayBuffer 更为高效——否则,你必须创建一个新大小的缓冲区副本。它还使得 JavaScript 在这方面与 WebAssembly 保持一致(Wasm 线性内存可以通过WebAssembly.Memory.prototype.grow() 调整大小)。

出于安全原因,SharedArrayBuffer 的大小无法缩小,只能增大。

构造函数

SharedArrayBuffer()

创建一个新的SharedArrayBuffer 对象。

静态属性

SharedArrayBuffer[Symbol.species]

返回用于构造SharedArrayBuffer 方法返回值的构造函数。

实例属性

属性定义于SharedArrayBuffer.prototype 并且被所有SharedArrayBuffer 实例所共享。

SharedArrayBuffer.prototype.byteLength

数组大小,以字节为单位。在构造数组时被确定,并且只能在可增大的SharedArrayBuffer上通过SharedArrayBuffer.prototype.grow() 方法来改变。

SharedArrayBuffer.prototype.constructor

创建实例对象的构造函数。对于SharedArrayBuffer 实例,其初始值为SharedArrayBuffer 构造函数。

SharedArrayBuffer.prototype.growable

只读。如果当前SharedArrayBuffer 可以增大,则返回true,否则返回false

SharedArrayBuffer.prototype.maxByteLength

当前SharedArrayBuffer 可以增大的最大长度,只读,以字节为单位。在构造数组时确定且无法更改。

SharedArrayBuffer.prototype[Symbol.toStringTag]

[Symbol.toStringTag] 属性的初始值是字符串"SharedArrayBuffer"。它被用于Object.prototype.toString()

实例方法

SharedArrayBuffer.prototype.grow()

增大当前SharedArrayBuffer 到指定大小,以字节为单位。

SharedArrayBuffer.prototype.slice()

返回一个新的SharedArrayBuffer,其内容是当前SharedArrayBufferbegin(含)到end(不含)的字节的副本。如果beginend 为负,则它是从数组的末尾开始的索引,而不是数组的开头。

示例

创建一个新的 SharedArrayBuffer

js
const sab = new SharedArrayBuffer(1024);

截取 SharedArrayBuffer

js
sab.slice(); // SharedArrayBuffer { byteLength: 1024 }sab.slice(2); // SharedArrayBuffer { byteLength: 1022 }sab.slice(-2); // SharedArrayBuffer { byteLength: 2 }sab.slice(0, 1); // SharedArrayBuffer { byteLength: 1 }

在 WebGL buffer 中使用

js
const canvas = document.querySelector("canvas");const gl = canvas.getContext("webgl");const buffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, buffer);gl.bufferData(gl.ARRAY_BUFFER, sab, gl.STATIC_DRAW);

规范

Specification
ECMAScript® 2026 Language Specification
# sec-sharedarraybuffer-objects

浏览器兼容性

参见

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp