Frontend Labs
⋯

39. SharedArrayBuffer and Atomics: real shared-memory concurrency

Unlike a regular ArrayBuffer (owned by one realm at a time), a SharedArrayBuffer can be given to multiple workers simultaneously, with all of them reading and writing the same underlying memory — this is genuine shared-memory multithreading, the first time JS ever had it.

// main.js
const sab = new SharedArrayBuffer(4);           // 4 bytes = one Int32
const view = new Int32Array(sab);
Atomics.store(view, 0, 0);

worker.postMessage(sab);   // NOT copied, NOT transferred — genuinely SHARED

worker.onmessage = () => console.log("final value:", Atomics.load(view, 0));
worker.postMessage("start");

// worker.js — receives the SAME memory, both threads can race on it
let sharedView;
self.onmessage = (e) => {
  if (e.data instanceof SharedArrayBuffer) { sharedView = new Int32Array(e.data); return; }
  for (let i = 0; i < 1000; i++) Atomics.add(sharedView, 0, 1);  // ATOMIC increment — no lost updates
  self.postMessage("done");
};

Atomics provides the lock-free primitives (add, compareExchange, load, store, wait, notify) required to touch shared memory safely — without them, two threads doing sharedView[0]++ concurrently is a classic data race (read-modify-write isn't atomic), silently dropping increments. Atomics.wait/notify implement real blocking synchronization (a condition-variable-like primitive) between worker threads — genuinely novel capability in JS, previously impossible without shared memory.

The security catch: SharedArrayBuffer was disabled globally across all major browsers in 2018 in response to Spectre (a shared-memory, high- resolution timer is exactly the primitive needed for that class of speculative-execution side-channel attack). It's back today only on pages that opt into cross-origin isolation:

# Required response headers on the top-level document to re-enable SharedArrayBuffer:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Without both headers set, typeof SharedArrayBuffer === "undefined" in the page — this trips up a lot of teams trying to ship WASM-threads-based tools (FFmpeg.wasm, SQLite-in-a-worker with true concurrency) who forget the cross-origin-isolation requirement is now mandatory.

Generated from real-life-JS-guide.md · 8 Oct 2026 16:36