SharedArrayBuffer

Baseline 廣泛可用 *

此功能已成熟,可在多種裝置和瀏覽器版本上使用。自 2021 年 12 月以來,它已在所有瀏覽器中可用。

* 此特性的某些部分可能存在不同級別的支援。

SharedArrayBuffer 物件用於表示通用的原始二進位制資料緩衝區,類似於 ArrayBuffer 物件,但它們可用於建立對共享記憶體的檢視。SharedArrayBuffer 不是 Transferable Object,而 ArrayBuffer 是可傳輸的。

描述

要使用 SharedArrayBuffer 物件在叢集中的一個代理(代理可以是網頁的主程式或其 Web Worker 之一)與其他代理共享記憶體,需要使用 postMessagestructured cloning

結構化克隆演算法接受 SharedArrayBuffer 物件和對映到 SharedArrayBuffer 物件的型別化陣列。在這兩種情況下,SharedArrayBuffer 物件都會被傳輸給接收者,從而在接收代理中產生一個新的、私有的 SharedArrayBuffer 物件(就像 ArrayBuffer 一樣)。但是,兩個 SharedArrayBuffer 物件引用的共享資料塊是同一個資料塊,在一個代理中對該資料塊的更改最終會在另一個代理中可見。

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

共享記憶體可以在 Worker 或主執行緒中同時建立和更新。根據系統(CPU、作業系統、瀏覽器)的不同,更改可能需要一段時間才能傳播到所有上下文。為了同步,需要使用 Atomics 操作。

SharedArrayBuffer 物件被一些 Web API 使用,例如

安全要求

鑑於 Spectre 的出現,共享記憶體和高解析度計時器在 2018 年初被有效地 停用。在 2020 年,一種新的、安全的方法被標準化,以重新啟用共享記憶體。

要使用共享記憶體,您的文件必須處於 安全上下文 並且 跨源隔離。您可以使用 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 物件而丟擲異常,因此跨執行緒共享記憶體可用。

API 可用性

根據是否採取了上述安全措施,各種記憶體共享 API 的可用性有所不同。

  • Atomics 物件始終可用。
  • 原則上,SharedArrayBuffer 物件始終可用,但遺憾的是,全域性物件上的建構函式是隱藏的,除非設定了上述兩個頭資訊,這是為了與 Web 內容相容。希望將來可以取消此限制。WebAssembly.Memory 仍可用於獲取例項。
  • 除非設定了上述兩個頭資訊,否則各種 postMessage() API 在遇到 SharedArrayBuffer 物件時會丟擲異常。如果設定了這些頭資訊,Window 物件和專用 Worker 上的 postMessage() 將正常工作並允許記憶體共享。

WebAssembly 共享記憶體

WebAssembly.Memory 物件可以使用 shared 建構函式標誌建立。當此標誌設定為 true 時,構造的 Memory 物件可以透過 postMessage() 在 Worker 之間共享,就像 SharedArrayBuffer 一樣,並且 Memory 物件支援的 buffer 是一個 SharedArrayBuffer。因此,上述在 Worker 之間共享 SharedArrayBuffer 的要求同樣適用於共享 WebAssembly.Memory

WebAssembly 執行緒提案還定義了一組新的 原子 指令。就像 SharedArrayBuffer 及其方法被無條件啟用一樣(只有執行緒之間的共享受到新頭資訊的限制),WebAssembly 原子指令也被無條件允許。

擴充套件 SharedArrayBuffer

可以透過在呼叫 SharedArrayBuffer() 建構函式時包含 maxByteLength 選項來使 SharedArrayBuffer 物件可擴充套件。您可以訪問其 growablemaxByteLength 屬性來查詢 SharedArrayBuffer 是否可擴充套件以及其最大大小。您可以透過呼叫 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.prototype.grow() 方法進行更改(如果 SharedArrayBuffer 可擴充套件)。

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,其內容是此 SharedArrayBuffer 中從 begin(含)到 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 緩衝區中使用它

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);

規範

規範
ECMAScript® 2026 語言規範
# sec-sharedarraybuffer-objects

瀏覽器相容性

另見