你以为懂 async/await?七种语言七种结果
A Design Space Exploration of Async/Await

许多现代语言都提供了 async/await 关键字,旨在让并发代码看起来像顺序代码。但布朗大学的研究团队发现,不同语言对 async/await 的实现差异远超预期。他们通过一个简单的伪代码程序测试了七种现代运行时,结果竟出现了四种不同的输出。研究揭示了九个关键的设计维度,如任务的生命周期、取消机制和异常传播等,解释了为何 Swift 和 Trio 等语言在相同代码下表现迥异。没有绝对的对错,只有不同的设计权衡。这篇论文通过形式化语义模型,清晰地展示了这些设计决策如何影响程序行为,帮助开发者真正理解自己所用语言的异步语义。
你实际上真的了解你所在语言的 async 语义吗?
HN 评论区
29- spankalee
哇,这篇文章真是帮大忙了,而且来得正是时候!
我正在开发一门带有 async/await 的新语言,不得不做出很多类似的决策,但我之前没有一个像这样条理清晰的框架来作为依据。很高兴看到自己最终的选择主要是 Trio,带一点 JavaScript 的味道。
我的语言(Zena)的 async 文档页面:https://zena-lang.dev/guide/async/ 我觉得我可能会再通读一遍,尝试更明确地指出这些决策点。
顺便提一句(fwiw),我发现这篇由 Trio 作者撰写的关于取消(cancellation)的文章非常有说服力:https://vorpus.org/blog/timeouts-and-cancellation-for-humans... 我正是基于它来设计 Zena 的取消机制的。
补充编辑:我确实希望这篇文章能在“取消”部分包含 JavaScript 的 AbortSignal。倒不是说它有多好,而是因为传递取消令牌(cancel tokens)是一种确实存在的模式。此外,还有一个维度是关于谁可以发起取消,以及像 AbortSignal 那样,任务是否需要主动选择加入(opt-in)以进行取消检查。
- biorach
一直以来都很清楚,不同的 async 运行时之间存在一些根本性的实现选择差异,但居然有 _九_ 个设计维度?天哪。
我觉得 async 具有欺骗性,因为它看起来像是语言中一个自包含且相对直接的方面。但实际上需要做很多设计决策,而且它们都有广泛的影响。
此外,我认为其中许多维度的影响尚未被完全理解,我们整体上仍在努力理解它们在具体实现中是如何发挥作用的。再加上其中一些影响的微妙性质,以及这些维度的各种组合……
我觉得一个很好的类比是编程语言中的词法作用域(lexical scope)与动态作用域(dynamic scope)。这是一个在编程语言设计早期争论了十多年的设计维度。直到随着时间的推移,人们通过具体的实现积累了经验,才逐渐明确词法作用域应成为默认选择,而动态作用域应仅限于各种特定领域。