JavaScript Hard technical 1 views 3 min read

What is the Atomics API and when should it be used?

Peer-reviewed by HireXTech Technical Panel Updated for 2025/2026 hiring Editorial standards
Practise this track
Interviewer Expectations for this Question
01
Core Competency

Assesses fundamental understanding of JavaScript conventions, runtime behavior, and memory/performance considerations.

02
Evaluation Criteria

Hiring managers look for precision, avoidance of ambiguous jargon, and ability to explain trade-offs under real production conditions.

Comprehensive Model Answer Verified Solution

The Atomics API provides atomic operations on SharedArrayBuffer, ensuring thread-safe access to shared memory in multi-threaded JavaScript (workers).

Basic atomic operations:

     const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4);
     const view = new Int32Array(sab);

     // Atomic store - write a value
     Atomics.store(view, 0, 42);

     // Atomic load - read a value
     const value = Atomics.load(view, 0); // 42

     // Atomic add - add and return old value
     const oldValue = Atomics.add(view, 0, 10); // returns 42, view[0] is now 52

     // Atomic sub - subtract
     Atomics.sub(view, 0, 2); // view[0] is now 50

     // Atomic exchange - swap values
     const prev = Atomics.exchange(view, 0, 100); // returns 50, view[0] is now 100

     // Compare and exchange
     const replaced = Atomics.compareExchange(view, 0, 100, 200);
     // If view[0] === 100, set it to 200 and return 100
     // Otherwise, return current value
     

Wait and notify (worker synchronization):

     // Main thread
     const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT);
     const view = new Int32Array(sab);

     worker.postMessage(sab);

     // Wait for worker to set value to 1
     Atomics.wait(view, 0, 0); // Blocks until view[0] !== 0
     console.log('Worker has finished');

     // Worker thread
     self.onmessage = function(e) {
       const view = new Int32Array(e.data);

       // Do some work
       performTask();

       // Signal completion
       Atomics.store(view, 0, 1);
       Atomics.notify(view, 0, 1); // Wake up one waiting thread
     };
     

Mutex implementation:

     class Mutex {
       constructor(sab, index) {
         this.sab = sab;
         this.index = index;
       }

       lock() {
         const view = new Int32Array(this.sab);
         while (true) {
           const oldValue = Atomics.compareExchange(view, this.index, 0, 1);
           if (oldValue === 0) {
             return; // Successfully acquired lock
           }
           Atomics.wait(view, this.index, 1); // Wait if locked
         }
       }

       unlock() {
         const view = new Int32Array(this.sab);
         Atomics.store(view, this.index, 0);
         Atomics.notify(view, this.index, 1);
       }
     }

     // Usage
     const mutex = new Mutex(sab, 0);
     mutex.lock();
     try {
       // Critical section
       criticalOperation();
     } finally {
       mutex.unlock();
     }
     

Counter with atomic operations:

     class AtomicCounter {
       constructor() {
         this.sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT);
         this.view = new Int32Array(this.sab);
       }

       increment() {
         return Atomics.add(this.view, 0, 1) + 1;
       }

       decrement() {
         return Atomics.sub(this.view, 0, 1) - 1;
       }

       get value() {
         return Atomics.load(this.view, 0);
       }

       set value(val) {
         Atomics.store(this.view, 0, val);
       }
     }
     

Available atomic operations:

     // Arithmetic
     Atomics.add(typedArray, index, value)
     Atomics.sub(typedArray, index, value)

     // Bitwise
     Atomics.and(typedArray, index, value)
     Atomics.or(typedArray, index, value)
     Atomics.xor(typedArray, index, value)

     // Memory
     Atomics.load(typedArray, index)
     Atomics.store(typedArray, index, value)
     Atomics.exchange(typedArray, index, value)
     Atomics.compareExchange(typedArray, index, expectedValue, replacementValue)

     // Synchronization
     Atomics.wait(typedArray, index, value, timeout)
     Atomics.notify(typedArray, index, count)

     // Utility
     Atomics.isLockFree(size)
     

When to use Atomics:

  • Sharing data between web workers
  • Implementing locks, semaphores, or other synchronization primitives
  • Building concurrent data structures
  • High-performance parallel computing
  • Avoiding race conditions in shared memory

Candidate Response Strategy & Interview Tips

  1. Start with a concise one-sentence summary: Deliver a direct, confident answer first before expanding into nuances.
  2. Demonstrate real-world trade-offs: Discuss where this approach excels and when you would avoid it in production systems.
  3. Discuss complexity & edge cases: Proactively explain time/space complexity or boundary conditions (null values, scale limits).
  4. Prepare for interviewer follow-ups: Technical hiring panels frequently probe deeper into concurrency, backward compatibility, or alternative libraries.
Related Topics & Skills
Spotted an error or have an alternative solution?