What are the differences between SharedArrayBuffer and ArrayBuffer?
Assesses fundamental understanding of JavaScript conventions, runtime behavior, and memory/performance considerations.
Hiring managers look for precision, avoidance of ambiguous jargon, and ability to explain trade-offs under real production conditions.
SharedArrayBuffer and ArrayBuffer are both fixed-length binary data buffers, but SharedArrayBuffer allows sharing memory between multiple workers/threads.
ArrayBuffer (not shared):
// Regular ArrayBuffer
const buffer = new ArrayBuffer(16);
const view = new Int32Array(buffer);
view[0] = 42;
console.log(view[0]); // 42
// Transferable but not shared
worker.postMessage(buffer, [buffer]);
// buffer is now neutered (length = 0)
SharedArrayBuffer (shared memory):
// Main thread
const sharedBuffer = new SharedArrayBuffer(16);
const sharedView = new Int32Array(sharedBuffer);
sharedView[0] = 42;
// Send to worker (shared, not transferred)
worker.postMessage(sharedBuffer);
// Both main thread and worker can access the same memory
sharedView[0] = 100; // Worker will see this change
Key differences:
| ArrayBuffer | SharedArrayBuffer |
|-------------|-------------------|
| Single context only | Multiple contexts (workers/threads) |
| Transferred (moved) between workers | Shared between workers |
| No synchronization needed | Requires Atomics for safe access |
| Always available | Requires secure context (HTTPS) |
| Original becomes neutered after transfer | Original remains valid |
Using Atomics with SharedArrayBuffer:
// Main thread
const sab = new SharedArrayBuffer(4);
const view = new Int32Array(sab);
worker.postMessage(sab);
// Atomic operations
Atomics.store(view, 0, 42); // Write atomically
Atomics.add(view, 0, 10); // Add 10 atomically
const value = Atomics.load(view, 0); // Read atomically
// Wait/notify pattern
Atomics.wait(view, 0, 0); // Wait until value changes
Atomics.notify(view, 0, 1); // Wake one waiter
Worker communication example:
// Main thread
const sharedBuffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2);
const sharedArray = new Int32Array(sharedBuffer);
const worker = new Worker('worker.js');
worker.postMessage({ buffer: sharedBuffer });
// Increment counter atomically
setInterval(() => {
const oldValue = Atomics.add(sharedArray, 0, 1);
console.log('Main thread incremented to:', oldValue + 1);
}, 1000);
// worker.js
self.onmessage = function(e) {
const sharedArray = new Int32Array(e.data.buffer);
setInterval(() => {
const oldValue = Atomics.add(sharedArray, 1, 1);
console.log('Worker incremented to:', oldValue + 1);
}, 1000);
};
Security requirements for SharedArrayBuffer:
// Requires these headers:
// Cross-Origin-Opener-Policy: same-origin
// Cross-Origin-Embedder-Policy: require-corp
// Check availability
if (typeof SharedArrayBuffer !== 'undefined') {
console.log('SharedArrayBuffer is available');
} else {
console.log('SharedArrayBuffer is not available');
}
Candidate Response Strategy & Interview Tips
- Start with a concise one-sentence summary: Deliver a direct, confident answer first before expanding into nuances.
- Demonstrate real-world trade-offs: Discuss where this approach excels and when you would avoid it in production systems.
- Discuss complexity & edge cases: Proactively explain time/space complexity or boundary conditions (null values, scale limits).
- Prepare for interviewer follow-ups: Technical hiring panels frequently probe deeper into concurrency, backward compatibility, or alternative libraries.