Zig 的 Io.Threaded:用普通线程实现可靠的系统调用取消
来源:matklad.github.io — 2026-08-06
📋 概述
matklad 介绍了 Zig 新 Io 接口的一个实现 Io.Threaded——一个"无趣的"纯线程实现,但它做了一件他想做很久、据他所知没别人做好的事:用阻塞式系统调用并<span class="highlight">完全支持取消</span>。文章厘清并发与并行:并行是确定性的硬件利用,而并发必然涉及取消。问题的核心是系统调用——循环代码里容易检查取消标志,但线程阻塞在内核的系统调用里时,语言 API 通常无法解除阻塞。Zig 的 Io.Threaded 在 POSIX 上用信号做绕路:取消线程设共享内存标志并循环发信号,直到被取消方确认;收到 EINTR 后检查标志决定重试还是确认取消并展开。用户侧取消具体化为 error.Canceled。
🔑 核心要点
- 并发必然涉及取消,而取消的关键难点在系统调用——循环里容易检查标志,但线程阻塞在内核时语言 API 通常无法解除。
- Io.Threaded 在 POSIX 用信号做绕路:取消线程设共享内存标志并循环发信号直到被取消方确认。
- 收到 EINTR 后线程检查标志:要么重试系统调用,要么确认取消并开始展开。
- 用户侧取消具体化为 error.Canceled,错误管理是取消、分支与报告的整合,Zig 实现了前两者——错误就是"取消加负载"。
- Windows 有更直接的机制,NT 的整体并发故事比 Unix 想得更周全。
- Java 的线程中断不支持中断系统调用(IOException 与 InterruptedException 无关);pthread_cancel 用信号+标志但不整合语言级取消,且整线程拆除昂贵,而 Zig 用线程池并从接口层面区分"可能并发"与"必须并发"。
💡 金句
并发几乎总是包含取消。凡是两个异步计算同时进行,总有一刻,其中一个发现另一个已不再必要、必须主动取消。
👍 0
👎 0
← 返回 Lobsters 首页