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 等待结果。

它还设计了几类同步工具:LockConditionThreadLocal。更激进的是,它尝试把 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、结构化克隆直接共享对象省掉传输协议和对象搬运
共享方式主要依赖 SharedArrayBufferMap、Array、普通对象可共享对对象图密集任务更友好
同步手段消息、SAB AtomicsLock、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 和竞态一起算账。