Signatur
Beschreibung
Atomics.store() ist eine statische Methode des Namensraums Atomics. Sie schreibt einen Wert atomar an eine Stelle in einem Integer-TypedArray. Atomar bedeutet: Andere Threads, zum Beispiel Web Worker oder Node.js-worker_threads, die denselben SharedArrayBuffer nutzen, sehen nie einen halb geschriebenen Wert. Außerdem sorgt der Aufruf für eine feste Reihenfolge der Speicherzugriffe (sequentiell konsistent): Alles, was vor dem store geschrieben wurde, ist für einen Thread sichtbar, der den Wert danach mit Atomics.load() liest.
Man nutzt die Methode vor allem, um einem anderen Thread etwas mitzuteilen, etwa mit Status-Flags („Daten bereit“, „Abbruch angefordert“), Zählern oder Indizes in Ringpuffern. Ein normaler Schreibzugriff wie ta[i] = v kann vom Compiler oder der CPU umsortiert werden. Er ist deshalb für die Abstimmung zwischen Threads nicht zuverlässig.
Wichtig: Die Methode gibt den umgewandelten Eingabewert zurück. Das ist weder der alte Wert (anders als bei Atomics.exchange()) noch zwingend der Wert, der tatsächlich im Array steht. Läuft der Wert über den Wertebereich des Elementtyps hinaus, steht im Array ein anderer Wert als der, den die Methode zurückgibt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $typedArray Pflicht | Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|BigInt64Array|BigUint64Array | Ein Integer-TypedArray, meist über einem SharedArrayBuffer. Float32Array, Float64Array und Uint8ClampedArray sind nicht erlaubt. |
|
| $index Pflicht | number | Position im typedArray, an die geschrieben wird. |
|
| $value Pflicht | number|bigint | Der zu schreibende Wert. Bei BigInt64Array/BigUint64Array muss es ein bigint sein, sonst eine Zahl. Zahlen werden vorher in eine Ganzzahl umgewandelt (Nachkommastellen fallen weg). |
Rückgabewert
BigInt). Er wird nicht auf den Wertebereich des Elementtyps gekürzt und ist nicht der vorherige Wert.Beispiele
Einfaches atomares Schreiben
const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4);
const ta = new Int32Array(sab);
const result = Atomics.store(ta, 0, 42);
console.log(result); // Rückgabewert
console.log(Atomics.load(ta, 0)); // Wert im Array
Rückgabewert vs. tatsächlich gespeicherter Wert
const ta = new Int8Array(new SharedArrayBuffer(2));
// Nachkommastellen werden abgeschnitten
console.log(Atomics.store(ta, 0, 12.9)); // 12
// Überlauf: Rückgabe ist 300, im Int8Array landet 300 mod 256 = 44
console.log(Atomics.store(ta, 1, 300)); // 300
console.log(ta[1]); // 44
Status-Flag zwischen Hauptthread und Worker (Node.js)
import { Worker } from 'node:worker_threads';
const sab = new SharedArrayBuffer(8);
const flags = new Int32Array(sab);
const worker = new Worker(`
const { workerData } = require('node:worker_threads');
const flags = new Int32Array(workerData);
Atomics.wait(flags, 0, 0); // schlafen, bis Index 0 nicht mehr 0 ist
console.log('Worker: Signal erhalten, Wert =', Atomics.load(flags, 0));
`, { eval: true, workerData: sab });
setTimeout(() => {
Atomics.store(flags, 0, 1); // Flag atomar setzen …
Atomics.notify(flags, 0, 1); // … und wartenden Worker wecken
}, 100);
BigInt64Array verwenden
const big = new BigInt64Array(new SharedArrayBuffer(16));
console.log(Atomics.store(big, 0, 9007199254740993n));
try {
Atomics.store(big, 1, 5); // number statt bigint
} catch (e) {
console.log(e.constructor.name);
}
// Wichtig · Fallstricke
- Rückgabewert-Falle: Die Methode gibt den umgewandelten Eingabewert zurück, nicht den alten Inhalt und nicht den gekürzten Wert im Array. Wer den alten Wert braucht, nimmt
Atomics.exchange(). - Fehler: Ein
TypeErrorkommt bei einem ungültigen Array-Typ (Float-Arrays,Uint8ClampedArray, normale Arrays) oder beim Mischen vonnumberundbigint. EinRangeErrorkommt bei einem Index außerhalb des Arrays. - Kein Aufwecken:
storeweckt keine Threads, die inAtomics.wait()warten. Dafür muss man zusätzlichAtomics.notify()aufrufen. - Nicht geteilter Speicher: Die Methode funktioniert auch mit einem normalen
ArrayBuffer. Einen Nutzen hat sie aber nur bei einemSharedArrayBuffer. - Browser-Kompatibilität:
Atomics.store()gibt es in allen modernen Browsern und in Node.js 8.10+.SharedArrayBufferist im Browser aber nur in einem cross-origin isolated Kontext verfügbar. Dafür braucht die Seite die HTTP-HeaderCross-Origin-Opener-Policy: same-originundCross-Origin-Embedder-Policy: require-corp. Prüfen lässt sich das mitcrossOriginIsolated. - Keine Lese-Ändern-Schreiben-Operation: Für atomares Hochzählen nimmt man
Atomics.add(), nichtloadplusstore. Sonst kann es zu Race Conditions kommen.