From error-handling to structured concurrency

⭐⭐⭐⭐⭐ | Nelson Elhage | blog.nelhage.com | 2026-03-23
并发编程 结构化并发 错误处理 Python

核心问题

单线程程序中,错误沿调用栈向上传播直到被捕获。但并发程序没有单一调用栈,如何组织错误处理代码?

两种常见方法

  • 打印错误,继续运行 (Python, Java) - 线程异常后程序继续,可能导致死锁
  • 立即终止整个程序 (Go, Rust) - 过于重量级

asyncio的"第三种方法"

Task对象可被等待,异常会传递给等待者。但如果没有等待Task,异常会被吞掉直到程序退出。

TaskLauncher模式

每个任务有明确父任务,父任务负责等待子任务异常。通过上下文管理器确保所有任务被等待。

取消机制的必要性

需要同时满足:1) 等待所有子任务确保发现错误 2) 快速响应任何子任务的错误。这需要一个机制来请求任意任务提前退出。

💡 核心洞察:
"我们基本上需要一个机制来请求任意任务提前退出,以响应不同任务中发生的事件。在协作式并发系统中可在await点限制取消范围。"

历史教训

历史上的取消机制如pthread_cancel、Java Thread.stop、Ruby Thread.terminate都非常危险。Go将取消编码到Context对象中,需要代码显式检查。

原文链接 →