Signatur
Beschreibung
SharedArrayBuffer ist ähnlich wie ArrayBuffer ein Container für rohe Binärdaten fester Größe. Im Gegensatz zu ArrayBuffer wird der Speicher jedoch nicht kopiert, wenn er an einen Worker übergeben wird – beide Threads teilen sich denselben Speicherbereich. Damit ist echter paralleler Zugriff auf gemeinsame Daten möglich, was für rechenintensive Anwendungen (z. B. Bild- oder Audioverarbeitung, Simulationen) entscheidend sein kann.
Da mehrere Threads gleichzeitig lesen und schreiben können, entstehen Race Conditions. Für sicheres, koordiniertes Arbeiten mit einem SharedArrayBuffer werden TypedArray-Ansichten (typischerweise Int32Array) zusammen mit Atomics-Operationen verwendet. Atomics stellt atomare Lese-/Schreib-Operationen sowie Synchronisationsprimitive (Atomics.wait(), Atomics.notify()) bereit.
Aus Sicherheitsgründen (Spectre/Meltdown) wurde SharedArrayBuffer 2018 zeitweise deaktiviert und ist seit 2020 nur noch in Cross-Origin Isolated-Kontexten verfügbar. Die Seite muss dazu die HTTP-Header Cross-Origin-Opener-Policy: same-origin und Cross-Origin-Embedder-Policy: require-corp senden. Der Status kann über crossOriginIsolated geprüft werden.
Ein SharedArrayBuffer kann mit postMessage() an Worker und andere Fenster übertragen werden (ohne Kopie, nur Übertragung der Referenz). Er ist nicht transferierbar im Sinne von Transferable, sondern wird als shared übergeben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $byteLength Pflicht | number | Größe des gemeinsam genutzten Speicherpuffers in Bytes. Der Speicher wird mit Nullen initialisiert. | |
| $options | object | {} | Optionales Konfigurationsobjekt. Unterstützt maxByteLength (number): Maximale Größe in Bytes für einen vergrößerbaren SharedArrayBuffer (ab ES2024 / growable-Feature). |
Rückgabewert
SharedArrayBuffer-Objekt der angegebenen Größe, mit Nullen initialisiert.Beispiele
Grundlegende Nutzung mit einem Worker
// Hauptthread
if (!crossOriginIsolated) {
console.error('Cross-Origin Isolation ist nicht aktiv – SharedArrayBuffer nicht verfügbar.');
} else {
// 4 Bytes = 1 Int32-Wert
const sab = new SharedArrayBuffer(4);
const view = new Int32Array(sab);
// Initialwert setzen
Atomics.store(view, 0, 42);
console.log('Hauptthread schreibt:', Atomics.load(view, 0)); // 42
const worker = new Worker('worker.js');
// SharedArrayBuffer wird NICHT kopiert, nur die Referenz geteilt
worker.postMessage(sab);
worker.onmessage = () => {
console.log('Worker hat geändert:', Atomics.load(view, 0)); // 100
};
}
// worker.js
// self.onmessage = ({ data: sab }) => {
// const view = new Int32Array(sab);
// Atomics.store(view, 0, 100);
// self.postMessage('done');
// };
Atomare Synchronisation zwischen Threads (Mutex-ähnlich)
// Gemeinsamer Puffer: Index 0 = Lock (0=frei, 1=belegt)
const sab = new SharedArrayBuffer(8);
const lock = new Int32Array(sab);
// Funktion: Sperre erwerben (blockierend – nur in Worker erlaubt!)
function acquireLock(lockView, index) {
while (Atomics.compareExchange(lockView, index, 0, 1) !== 0) {
// Warte, bis die Sperre frei ist
Atomics.wait(lockView, index, 1);
}
}
// Funktion: Sperre freigeben
function releaseLock(lockView, index) {
Atomics.store(lockView, index, 0);
Atomics.notify(lockView, index, 1);
}
// Beispiel im Worker-Kontext:
// acquireLock(lock, 0);
// try {
// // Kritischer Abschnitt – nur ein Thread gleichzeitig
// const dataView = new Int32Array(sab);
// dataView[1] += 1;
// } finally {
// releaseLock(lock, 0);
// }
console.log('Lock initialisiert:', Atomics.load(lock, 0)); // 0 (frei)
// Wichtig · Fallstricke
Sicherheit (Spectre): Seit 2018 ist SharedArrayBuffer nur in Cross-Origin Isolated-Kontexten verfügbar. Die erforderlichen HTTP-Header sind: Cross-Origin-Opener-Policy: same-origin und Cross-Origin-Embedder-Policy: require-corp. Ohne diese Header ist SharedArrayBuffer undefined.
Kein Transfer, sondern Sharing: Bei postMessage() wird ein SharedArrayBuffer in das transfer-Array übergeben? Nein – er wird im zweiten Argument als normales Objekt übergeben (nicht transferiert), da er ohnehin shared ist. Ihn in die Transfer-Liste aufzunehmen würde einen Fehler verursachen.
Atomics ist Pflicht: Direktes Lesen/Schreiben auf geteilten Puffern ohne Atomics führt zu undefiniertem Verhalten durch Race Conditions. Verwende immer Atomics.load(), Atomics.store(), Atomics.add() etc.
Wachstum (growable): Ab neueren Browser-Versionen kann ein SharedArrayBuffer mit maxByteLength-Option erstellt und via sab.grow(newSize) vergrößert werden. Die Eigenschaft sab.growable zeigt an, ob dies möglich ist.