Threads, Atomics and Shared Memory

23.1 Building Blocks

Shared memory: new WebAssembly.Memory({ initial, maximum, shared: true }), backed by a SharedArrayBuffer.

Threads = Web Workers (browser) or host threads (runtimes), each with its own instance sharing the same memory.

Atomic instructions (prefix 0xFE): i32.atomic.load/store, i32.atomic.rmw.add/sub/and/or/xor/xchg/cmpxchg, memory.atomic.wait32/wait64, memory.atomic.notify, atomic.fence.

(module
  (memory (import "env" "memory") 1 10 shared)
  (func (export "increment") (param $addr i32) (result i32)
    (i32.atomic.rmw.add (local.get $addr) (i32.const 1)))     ;; returns the old value
  (func (export "wait") (param $addr i32) (param $expected i32)
    (drop (memory.atomic.wait32 (local.get $addr) (local.get $expected) (i64.const -1))))  ;; block until notified
  (func (export "wake") (param $addr i32)
    (drop (memory.atomic.notify (local.get $addr) (i32.const 1)))))

23.2 Cross-Origin Isolation (Required in Browsers)

The main thread can't block (Atomics.wait isn't allowed on the main thread), so do blocking work in workers.

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp      (or credentialless)
console.log(self.crossOriginIsolated);   // must be true to use SharedArrayBuffer

23.3 Language Support

C/C++ (Emscripten) -pthread, pthreads API, -sPTHREAD_POOL_SIZE, -sPROXY_TO_PTHREAD

wasm-bindgen-rayon (Rayon thread pool), nightly -C target-feature=+atomics,+bulk-memory with build-std. wasm32-wasip1-threads for WASI.

wasi-threads (wasm32-wasip1-threads, Wasmtime/WAMR support). The future shared-everything-threads proposal.

Not yet multi-threaded on Wasm (goroutines run on one thread)

23.4 Patterns

Worker pools for parallel image processing, physics, and compression. Lock-free ring buffers between the audio thread (AudioWorklet) and the Wasm DSP. Use Atomics in JS to coordinate with Wasm.