Glossary / Atomics
Atomics
Atomics is the ECMAScript API for synchronizing agents that access shared memory, usually a SharedArrayBuffer. It provides indivisible operations and ordering guarantees for supported integer typed arrays, so workers can coordinate state without corrupting it through overlapping reads and writes.
Why ordinary shared reads and writes are insufficient
A shared integer update such as view[0]++ is a read, addition, then write. Another worker can interleave between those steps and overwrite an update. Atomic read-modify-write methods such as Atomics.add perform the operation as one indivisible action. Atomicity does not automatically make an entire multi-step algorithm correct: protocols still need states, ownership rules, and transitions.
The API accepts integer typed arrays over shared memory (including Int32Array, BigInt64Array, and unsigned variants where the operation permits them). It does not make arbitrary object graphs shared; ordinary objects are sent through messaging or structured cloning.
Core operations and return values
const state = new Int32Array(new SharedArrayBuffer(4));
const previous = Atomics.add(state, 0, 1); // returns old value: 0
const current = Atomics.load(state, 0); // 1
const old = Atomics.compareExchange(state, 0, 1, 2);
// old is 1; state[0] is now 2
load and store perform atomic access. exchange replaces and returns the old value. compareExchange conditionally replaces the value only when it equals an expected value, enabling locks and state machines. Arithmetic and bitwise operations return the value before the operation, a frequent source of mistakes.
Atomics.wait parks an agent while a location has an expected value and returns a status such as "ok", "not-equal", or "timed-out". It blocks the calling agent and is forbidden on the browser main thread. Atomics.notify wakes waiting agents. Atomics.waitAsync provides a nonblocking wait where supported; check target runtime support before using it.
Correctness patterns and hazards
Use a state machine: define which agent may write each field, the legal state transitions, publication of associated data, and shutdown behavior. Use compare-and-swap loops only when retries are bounded or contention is understood. A lock can deadlock if its owner terminates before releasing it. A wait can be missed if the protocol checks and sleeps without correctly coordinating the state transition. Avoid spinning: it consumes CPU and can starve the worker that would make progress.
Atomics operations are sequentially consistent in the ECMAScript memory model, which is a strong ordering model. Still, a sequence of operations is not one transaction. Prefer message passing unless profiling demonstrates that shared memory solves a real copying or latency bottleneck. Shared memory also requires lifecycle ownership: all agents must know when a buffer or protocol is no longer in use.
Interview questions
- Why is
view[0]++unsafe across workers? It is a compound read-modify-write and can lose an interleaved update. - What does
Atomics.compareExchangereturn? The old value, whether or not it matched the expected value. - Does
Atomicsmake an algorithm race-free automatically? No; it makes individual operations atomic and ordered, while the algorithm must still define valid protocol transitions. - Why not use a spinlock? It burns CPU and may prevent the lock holder from getting scheduled, especially under oversubscription.
- Can
Atomics.waitrun on the browser main thread? No; it would block rendering and input, so browsers prohibit it there.