Bun 作者 Jarred Sumner 最近在 oven-sh/WebKit fork 上提交了 GitHub PR #249。目标很明确:给 JavaScriptCore 增加 shared-memory threads,也就是共享同一个堆的 JavaScript 线程。
这件事容易被误读成“Safari 要有新线程 API 了”。不是。它现在只是 oven-sh/WebKit fork 里的实验性 PR,不代表 WebKit 或 Safari 官方已经采纳。
更准确的看法是:Jarred 在试探一个老问题——JavaScript 能不能不靠 Worker 传消息,而让多个线程直接共享对象图。
PR #249 做了什么:把线程放进同一个堆
这个 PR 的核心 API 很直白。
new Thread(fn) 把一个函数放到新线程执行。join() 阻塞等待结果。asyncJoin() 用 Promise 等待结果。
它还设计了几类同步工具:Lock、Condition、ThreadLocal。更激进的是,它尝试把 Atomics 扩展到普通对象属性上,比如对 obj.k 做原子加减、比较交换、等待和通知。
关键点不在 API 名字,而在内存模型。
按照 PR 描述,这套方案希望让多个 JavaScript 线程跑在同一个堆里,共享对象,并且不靠一个全局锁把所有执行串起来。原文也提到,当前分支已能让并行 JavaScript 在四级 JIT 下执行,线程测试套件在这种模式下通过。
但状态同样写得很重:experimental、not working yet。
后面还需要 TSan 清理、fuzzing、长时间 soak 和性能验证。作者也明确承认,它可能永远不会合并。
所以它不是新特性发布,更像一次把“共享堆多线程”推到 JavaScriptCore 内部验证的工程样机。
它和 Web Worker 的差别:少了搬运,多了竞态
JavaScript 不是没有并行。浏览器有 Web Worker,Node.js 有 worker_threads,Deno 和 Bun 也都有自己的并行能力。
但这些能力大多围绕 Worker 模型展开:各跑各的堆,通过消息通信。要共享底层内存,主要依赖 SharedArrayBuffer 这类字节缓冲区。
PR #249 想改的是这一层。
| 对比项 | Web Worker / worker_threads 常见模型 | PR #249 试探的模型 | 工程含义 |
|---|---|---|---|
| 堆模型 | 独立堆 | 同一堆 | 少复制,更多共享状态 |
| 数据传递 | postMessage、结构化克隆 | 直接共享对象 | 省掉传输协议和对象搬运 |
| 共享方式 | 主要依赖 SharedArrayBuffer | Map、Array、普通对象可共享 | 对对象图密集任务更友好 |
| 同步手段 | 消息、SAB Atomics | Lock、Condition、扩展 Atomics | 更接近传统多线程编程 |
| 主要风险 | 通信成本、数据拆分成本 | 数据竞争、锁竞争、调试难度 | 便利性换来责任转移 |
这就是它有意思的地方。
Worker 模型像是“分家过日子”:安全边界清楚,但要频繁搬东西。共享堆线程像是“同屋共用”:效率可能更高,但钥匙、账本和规矩都要管好。
对工具链开发者,这个差别很现实。
解析器、打包器、模块图分析、服务端缓存,常常围绕大量 JavaScript 对象运行。用 Worker 做并行时,团队通常要拆任务、设计消息协议、处理结构化克隆,或者把数据改写进 SharedArrayBuffer。
如果共享堆线程真能成立,一个打包器可以让多个线程读取同一份模块图。一个 Bun 服务端框架也可能让多个请求线程访问同一个共享 Map 缓存。
但现在最理性的动作不是迁移。
运行时和工具链团队可以开始看 API 形态、评估哪些内部对象图最适合共享。生产项目不该基于这个 PR 改架构。更不用为了它推迟现有 Worker 方案。
现在最该看什么:不是语法,是安全账和性能账
共享堆多线程的麻烦,不会因为 API 看起来短就消失。
VM 可以努力保证内存安全,避免 JSValue 撕裂、类型混淆或堆损坏。可业务逻辑里的竞态,仍然落在开发者身上。
一个共享 Map 少加一把锁,未必立刻崩溃。更常见的结果是脏读、丢更新、偶发错误。多线程最难的地方,往往不是跑起来,而是错得不稳定。
性能也不能提前下结论。
PR 里有一些早期测量和阶段性预期,比如开启 flag 后的串行回归、线程内存占用、共享对象转移成本等。但这些还不是最终基准。
真正要看的,是对象共享扩大后,JIT 假设会被打掉多少,锁竞争会不会吃掉并行收益,结构变化和 GC 压力会不会让收益变薄。
接下来有三个判断条件,比 API 讨论更重要:
- PR #249 是否继续在 oven-sh/WebKit fork 中推进,而不是停在实验分支;
--useJSThreads下的 TSan、fuzzing、soak 是否能过关;- Bun 是否用真实负载验证,比如打包、解析、服务器共享缓存,而不是只跑微基准。
如果这些条件没有过,PR #249 最多说明方向值得试。它还不能说明 JavaScript 共享堆线程已经能进入生产。
回到开头那个问题:这不是 Safari 新功能,也不是 Bun 开发者明天就该换用的新工具。
它真正给出的信号是,Worker 之外的 JavaScript 并行路线,已经有人开始往引擎深处凿。路能不能通,要看锁、JIT、GC 和竞态一起算账。
