Ce face Atomics și SharedArrayBuffer
SharedArrayBuffer este un ArrayBuffer pe care mai mulți workers îl văd în același timp. Când două fire modifică aceeași poziție deodată, o operație obișnuită (a[0]++) poate pierde actualizări. Metodele Atomics fac fiecare operație dintr-o bucată: add, sub, and, or, xor, exchange, compareExchange, load, store.
Atomics.wait oprește firul până când altul apelează Atomics.notify pe aceeași poziție (nu este permis pe firul principal al browserului); waitAsync este varianta cu promisiune. isLockFree spune dacă operațiile pe o anumită mărime sunt implementate direct de procesor, iar pause este o pauză foarte scurtă pentru buclele de așteptare. SharedArrayBuffer are și slice și grow (mărire, dacă a fost creat cu maxByteLength).
În browser, SharedArrayBuffer este disponibil doar pe pagini izolate (anteturile Cross-Origin-Opener-Policy și Cross-Origin-Embedder-Policy).
Parametri
| Parametru | Descriere |
|---|---|
typedArray |
Un typed array întreg (de obicei Int32Array) creat peste un SharedArrayBuffer. |
indice |
Poziția elementului. |
valoare |
Valoarea folosită în operație. |
Ce returnează
Majoritatea operațiilor returnează valoarea veche de pe poziție; load returnează valoarea curentă.
Exemple
Exemplul 1: Operații atomice pe memorie partajată
const memorie = new SharedArrayBuffer(8);
const contoare = new Int32Array(memorie);
console.log(Atomics.add(contoare, 0, 5));
console.log(Atomics.add(contoare, 0, 3));
console.log(Atomics.load(contoare, 0));
console.log(Atomics.compareExchange(contoare, 0, 8, 100), Atomics.load(contoare, 0));
console.log(Atomics.compareExchange(contoare, 0, 8, 0), Atomics.load(contoare, 0));
console.log(Atomics.isLockFree(4));
Rezultat
0
5
8
8 100
100 100
true
Exemplul 2: Un contor incrementat de mai mulți workers (Node.js)
import { Worker } from "node:worker_threads";
const memorie = new SharedArrayBuffer(4);
const cod = `
const { workerData } = require("node:worker_threads");
const c = new Int32Array(workerData);
for (let i = 0; i < 100000; i++) Atomics.add(c, 0, 1);
`;
await Promise.all([1, 2, 3, 4].map(() => new Promise((gata) => {
new Worker(cod, { eval: true, workerData: memorie }).on("exit", gata);
})));
console.log(Atomics.load(new Int32Array(memorie), 0));
Rezultat
400000
Greșeli frecvente
- Incrementezi memoria partajată cu
a[0]++din mai multe fire. Unele incrementări se pierd; foloseșteAtomics.add. - Apelezi
Atomics.waitpe firul principal al browserului și primeștiTypeError. FoloseșteAtomics.waitAsyncsau mută așteptarea într-un worker.
Comenzi înrudite
ArrayBuffer: Un bloc de memorie brută, de lungime dată în octeți; citit și scris prin typed arrays sau DataView.Typed arrays (Uint8Array, Float64Array...): Tablouri de lungime fixă cu numere de un singur tip, pentru date binare: imagini, fișiere, audio, rețea.Worker (Web Workers): Rulează cod JavaScript pe un fir separat, ca operațiile grele să nu blocheze pagina.