SharedArrayBuffer
Baseline 廣泛可用 *
SharedArrayBuffer 物件用於表示通用的原始二進位制資料緩衝區,類似於 物件,但它們可用於建立對共享記憶體的檢視。ArrayBufferSharedArrayBuffer 不是 ,而 Transferable ObjectArrayBuffer 是可傳輸的。
描述
要使用 SharedArrayBuffer 物件在叢集中的一個代理(代理可以是網頁的主程式或其 Web Worker 之一)與其他代理共享記憶體,需要使用 和 postMessagestructured cloning。
結構化克隆演算法接受 SharedArrayBuffer 物件和對映到 SharedArrayBuffer 物件的型別化陣列。在這兩種情況下,SharedArrayBuffer 物件都會被傳輸給接收者,從而在接收代理中產生一個新的、私有的 SharedArrayBuffer 物件(就像 一樣)。但是,兩個 ArrayBufferSharedArrayBuffer 物件引用的共享資料塊是同一個資料塊,在一個代理中對該資料塊的更改最終會在另一個代理中可見。
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
共享記憶體可以在 Worker 或主執行緒中同時建立和更新。根據系統(CPU、作業系統、瀏覽器)的不同,更改可能需要一段時間才能傳播到所有上下文。為了同步,需要使用 操作。Atomics
SharedArrayBuffer 物件被一些 Web API 使用,例如
安全要求
鑑於 Spectre 的出現,共享記憶體和高解析度計時器在 2018 年初被有效地 停用。在 2020 年,一種新的、安全的方法被標準化,以重新啟用共享記憶體。
要使用共享記憶體,您的文件必須處於 安全上下文 並且 跨源隔離。您可以使用 和 Window.crossOriginIsolated 屬性來檢查文件是否跨源隔離。WorkerGlobalScope.crossOriginIsolated
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.Memoryshared 建構函式標誌建立。當此標誌設定為 true 時,構造的 Memory 物件可以透過 postMessage() 在 Worker 之間共享,就像 SharedArrayBuffer 一樣,並且 Memory 物件支援的 buffer 是一個 SharedArrayBuffer。因此,上述在 Worker 之間共享 SharedArrayBuffer 的要求同樣適用於共享 WebAssembly.Memory。
WebAssembly 執行緒提案還定義了一組新的 原子 指令。就像 SharedArrayBuffer 及其方法被無條件啟用一樣(只有執行緒之間的共享受到新頭資訊的限制),WebAssembly 原子指令也被無條件允許。
擴充套件 SharedArrayBuffer
可以透過在呼叫 建構函式時包含 SharedArrayBuffer()maxByteLength 選項來使 SharedArrayBuffer 物件可擴充套件。您可以訪問其 和 growable 屬性來查詢 maxByteLengthSharedArrayBuffer 是否可擴充套件以及其最大大小。您可以透過呼叫 方法來為可擴充套件的 grow()SharedArrayBuffer 分配新大小。新位元組將被初始化為 0。
這些功能使得擴充套件 SharedArrayBuffer 更高效 — 否則,您必須建立一個具有新大小的緩衝區副本。它還使 JavaScript 在這方面與 WebAssembly 保持一致(Wasm 線性記憶體可以使用 進行大小調整)。WebAssembly.Memory.prototype.grow()
出於安全原因,SharedArrayBuffer 不能縮小,只能增大。
建構函式
-
建立一個新的
SharedArrayBuffer物件。
靜態屬性
-
返回用於構造
SharedArrayBuffer方法的返回值的建構函式。
例項屬性
這些屬性定義在 SharedArrayBuffer.prototype 上,並由所有 SharedArrayBuffer 例項共享。
-
陣列的大小(以位元組為單位)。此大小在陣列構造時確定,並且只能使用
方法進行更改(如果SharedArrayBuffer.prototype.grow()SharedArrayBuffer可擴充套件)。 -
建立例項物件的建構函式。對於
SharedArrayBuffer例項,初始值為建構函式。SharedArrayBuffer -
只讀。如果
SharedArrayBuffer可擴充套件,則返回true,否則返回false。 -
可讀寫的最大長度(以位元組為單位),
SharedArrayBuffer可擴充套件至此。此長度在陣列構造時確定,並且無法更改。 -
[Symbol.toStringTag]屬性的初始值為字串"SharedArrayBuffer"。此屬性用於。Object.prototype.toString()
例項方法
-
將
SharedArrayBuffer擴充套件到指定的大小(以位元組為單位)。 -
返回一個新的
SharedArrayBuffer,其內容是此SharedArrayBuffer中從begin(含)到end(不含)的位元組副本。如果begin或end為負數,則表示相對於陣列末尾的索引,而不是相對於開頭的索引。
示例
建立新的 SharedArrayBuffer
const sab = new SharedArrayBuffer(1024);
切片 SharedArrayBuffer
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 緩衝區中使用它
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 |
瀏覽器相容性
載入中…
另見
AtomicsArrayBuffer- JavaScript 型別化陣列指南
- Web Workers
- TC39 ecmascript-sharedmem 提案中的 Shared Memory – a brief tutorial
- hacks.mozilla.org 上的 A Taste of JavaScript's New Parallel Primitives(2016 年)
- Chrome 團隊的 COOP and COEP explained(2020 年)
Cross-Origin-Opener-PolicyCross-Origin-Embedder-PolicyCross-Origin-Resource-PolicyWindow.crossOriginIsolated和WorkerGlobalScope.crossOriginIsolated- developer.chrome.com 上的 SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92(2021 年)