transferable机制通过显式transfer list移交arraybuffer所有权,实现零拷贝:原线程buffer变detached,目标线程重建视图直接访问同一内存;未传transfer list则退化为结构化克隆。

直接用 transferable 机制移交 ArrayBuffer 所有权,就能绕过结构化克隆,实现零拷贝传输。
Transferable 移交是核心手段
ArrayBuffer 本身不能直接跨线程共享,但可通过 transfer list 把它的底层 Native 内存“移交给”目标线程。移交后,原线程的 ArrayBuffer.buffer 变为 detached(即 null),不再可读写;目标线程则获得同一块物理内存的访问权,只需重建 JS 对象壳(如 Uint8Array、Float32Array),无需复制数据。
- 必须显式传入
postMessage(data, [arrayBuffer])的第二个参数,否则仍走结构化克隆 - 移交对象只能是 ArrayBuffer 或其视图的
.buffer,普通数组、JSON、未绑定 buffer 的 TypedArray 均不支持 - 移交后主线程若再访问该 buffer,会抛出
TypeError: Cannot perform %ArrayBuffer% constructor on a detached ArrayBuffer
SharedArrayBuffer 适合高频读写场景
当多个线程需**同时读写同一块内存**(比如实时音视频处理、游戏状态同步),应选 SharedArrayBuffer。它分配的是真正共享的底层内存,所有线程通过相同地址访问,但必须配合 Atomics 进行同步操作。
- 创建前必须确保页面启用跨域隔离:服务端需返回
Cross-Origin-Embedder-Policy: require-corp和Cross-Origin-Opener-Policy: same-origin响应头 - 主线程和 Worker 都要基于同一 SharedArrayBuffer 构建类型一致、偏移对齐的视图(如都用
new Int32Array(sab)) - 禁止直接赋值(如
view[0] = 1),必须用Atomics.store(view, 0, 1)等原子操作保证线程安全
拷贝方式仅在必要时使用
只有当**主线程和子线程都需要独立持有同一份数据副本**时,才用结构化克隆(即不传 transfer list)。这种模式适用于小数据或需保留原始缓冲区的场景,但性能代价明显:
- 数据量越大,序列化/反序列化耗时越长,内存占用翻倍
- ArkTS 中 TaskPool 默认走转移,若需拷贝,须显式调用
task.setTransferList([]) - 拷贝后两端 ArrayBuffer 完全独立,修改互不影响
实际选择建议
优先按使用意图判断:
- 单向计算任务(如图片滤镜、音频解码)→ 用 transferable 移交,高效且简单
- 双向低延迟协作(如多 Worker 并行更新统计值)→ 用 SharedArrayBuffer + Atomics
- 只读分发或需保留原始 buffer → 接受结构化拷贝,但控制数据规模










