SharedArrayBuffer & Atomics: Multi-Thread Memory and Futex Locking
- Last updated
- Prerequisites:
- Web Workers and message passing basics
- Understanding of typed arrays and ArrayBuffer
- sharedarraybuffer
- atomics
- worker
- memory-model
- futex
- concurrency
Read at your depth
The practical view
SharedArrayBuffer is an ArrayBuffer that multiple workers can access at the same time — no copying/messaging. You view it with a typed array: const sab = new SharedArrayBuffer(4); const view = new Int32Array(sab);. Atomics provides atomic operations: Atomics.add(view, 0, 1), Atomics.load, Atomics.store, Atomics.compareExchange, and Atomics.wait / Atomics.notify for blocking coordination. This enables lock-free data structures and faster shared state than postMessage copying. Note: SharedArrayBuffer requires cross-origin isolation (COOP/COEP headers) in browsers for security (Spectre mitigation).
The same idea in other frameworks
React Native and web worker offloading can use SharedArrayBuffer for image/frame buffers between threads.Angular apps rarely use SAB directly; heavy computation can be offloaded to workers sharing typed arrays.Vue's reactivity stays single-threaded; SAB is only relevant when delegating compute to workers in large data apps.SvelteKit has no special SAB integration — but a Svelte app can pair workers with SAB for data-heavy visualizations.Legacy vs modern
Worker coordination: postMessage copying vs SharedArrayBuffer + Atomics
postMessage clones data per message (allocation + serialization); a SharedArrayBuffer shares the same bytes with atomic synchronization for zero-copy handoff.
worker.postMessage(bigData); // ❌ OLD: structured-clones the whole buffer per messageconst sab = new SharedArrayBuffer(100_000_000); // ✅ NEW: zero-copy shared region
Atomics.store(view, i, value); Atomics.notify(view, 0);Interview gotchas
Context
This tests awareness of the security-driven deployment constraint, not just API knowledge — a real gotcha when shipping SAB-based apps.
The mechanical answer
SharedArrayBuffer was disabled after the Spectre/Meltdown CPU vulnerabilities because shared memory plus high-resolution timers enable timing side channels. Browsers re-enabled it only inside a cross-origin-isolated context: the page must serve COOP: same-origin and COEP: require-corp (and the response must be valid for those headers), and self-isolated iframes. Without those headers, window.SharedArrayBuffer and window.Atomics are undefined or throw (in some engines they are disabled entirely). This affects deployment: CDNs, third-party scripts, and subresources must all satisfy the COEP requirement, or the feature is unavailable in production even though it works in localhost dev.
Trap
The naive answer is 'SAB is just an ArrayBuffer you share, no setup needed'. In modern browsers the security headers are mandatory. Another trap: assuming the error is a feature-availability check you can polyfill — SAB cannot be polyfilled because it requires OS-level shared memory; you must restructure headers or fall back to postMessage cloning.
Context
This separates candidates who understand the event loop constraint from those who treat Atomics as a magic API — the futex mechanism is the real substance.
The mechanical answer
Atomics.wait blocks the calling thread until the memory location changes or a timeout expires. On the main thread, blocking freezes the entire page — event loop, rendering, and input — so the spec forbids it (it throws a TypeError). On a worker it is fine because the thread is not the UI thread. Under the hood, Atomics.wait/notify are implemented with OS futex primitives: the engine parks the thread on a wait queue associated with the address, and Atomics.notify wakes up to N waiters on that address. The atomic store that precedes the notify must be visible to the waiter for correct ordering — which is why the memory model treats these as seq_cst operations.
Trap
The naive answer is 'Atomics.wait is just a busy-wait loop you can use anywhere'. It is a real blocking primitive tied to OS futexes and cannot run on the main thread. Another trap: forgetting that the notified waiter may not immediately see the latest store without proper ordering — Atomics.load after waking can return a stale value if the writer did not use an atomic store/notify pair consistently. Candidates who connect wait/notify to the futex and the memory-model ordering demonstrate depth.