
在 WebAssembly 中,若需在主线程与 Web Worker 间安全共享内存,必须显式声明 shared 内存;仅导出普通内存(ArrayBuffer)无法实现跨线程共享,正确做法是在 .wat 模块中使用 (memory ... shared) 并确保运行环境支持。
在 webassembly 中,若需在主线程与 web worker 间安全共享内存,必须显式声明 `shared` 内存;仅导出普通内存(`arraybuffer`)无法实现跨线程共享,正确做法是在 `.wat` 模块中使用 `(memory ... shared)` 并确保运行环境支持。
WebAssembly 默认内存是独占的,其底层 buffer 类型为 ArrayBuffer,不可被多个 JavaScript 线程同时访问。要实现真正的线程间共享(例如主线程与 Web Worker 协同操作同一块内存),必须启用 共享内存(Shared Memory) 支持——这要求两方面协同:Wasm 模块声明 + 运行时环境支持。
✅ 正确声明共享内存
在文本格式(.wat)中,需显式添加 shared 关键字,并指定最小与最大页数(最小页数为必需,最大页数可选但推荐设置以支持动态增长):
(module (memory (export "memory") 1 2 shared) // ← 关键:shared + 明确 min/max 页数 (data (i32.const 0) "Hello World!") )
编译后(如使用 wat2wasm),该模块将生成支持 SharedArrayBuffer 的内存实例。
✅ JavaScript 端验证与使用
加载后,memory.buffer 将自动变为 SharedArrayBuffer(前提是浏览器支持且模块已正确声明):
fetch('hello.wasm')
.then(res => res.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes))
.then(result => {
const memory = result.instance.exports.memory;
// ✅ 安全检查:必须是 SharedArrayBuffer 才能跨线程共享
if (!(memory.buffer instanceof SharedArrayBuffer)) {
throw new Error("Memory is not shared — check Wasm module declaration and browser support.");
}
const sab = memory.buffer;
const view = new Int32Array(sab); // 或 Uint8Array 等
// 示例:主线程写入,Worker 可立即读取(配合 Atomics)
Atomics.store(view, 0, 42);
console.log("Written value:", Atomics.load(view, 0)); // 42
});
⚠️ 重要注意事项:
- 浏览器支持:Chrome 68+、Firefox 71+、Safari 15.4+ 支持 SharedArrayBuffer,但需满足跨域隔离策略(即响应头含 Cross-Origin-Embedder-Policy: require-corp 和 Cross-Origin-Opener-Policy: same-origin);
- 安全限制:未启用跨域隔离时,SharedArrayBuffer 将被禁用(返回 undefined),此时即使 Wasm 声明了 shared,运行时也会降级为普通内存;
- 动态增长限制:SharedArrayBuffer 不支持 grow()(Wasm memory.grow 指令在共享内存上会失败),因此务必在声明时合理设定 max 页数(1 页 = 64 KiB);
- 并发安全:共享内存访问必须配合 Atomics API(如 Atomics.wait()/Atomics.notify()/Atomics.add())进行同步,避免竞态条件。
✅ 总结
导出可共享的 WebAssembly 内存不是“单纯导出即可”,而是需:
- 在 Wasm 模块中声明 (memory ... shared);
- 编译工具链支持(如最新版 WABT、wabt、binaryen);
- 浏览器启用跨域隔离;
- JavaScript 层使用 SharedArrayBuffer + Atomics 进行线程安全操作。
只有四者齐备,才能真正实现高效、安全的多线程内存共享。











