crossbeam 源码解析
全卷只对着一个发布提交写:
| crate | 版本 | tag | commit | 日期 |
|---|---|---|---|---|
crossbeam、crossbeam-channel、crossbeam-deque、crossbeam-epoch、crossbeam-utils、crossbeam-queue | 0.8.5、0.5.17、0.8.8、0.9.21、0.8.23、0.3.14 | 各 crate 自己的 tag,如 crossbeam-channel-0.5.17 | 2920c984(v0.8 发布分支) | 2026-09-06 |
crossbeam-skiplist | 0.1.3 | crossbeam-skiplist-0.1.3 | 3aa2598e(main) | 2024-01-08 |
crossbeam 是 Rust 的并发工具箱。它不是运行时,也不是线程池,而是几块互相独立、可以单独依赖的积木:缓存行填充 CachePadded、退避 Backoff、任意类型的原子单元 AtomicCell、基于纪元的内存回收(EBR)、Chase-Lev 工作窃取双端队列、MPMC channel 和 select!、无锁队列 ArrayQueue / SegQueue、并发跳表。它的一部分后来进了标准库:Rust 1.63 的 std::thread::scope,以及 1.67.0 起 std::sync::mpsc 的现行实现,就是从 crossbeam-channel 移植的。另一部分至今只在这里:rayon 的调度器建在它的 deque 上。
它和前几卷的关系:tokio 卷讲的是一个 async 运行时,本卷讲的是线程和原子变量这一层,没有 Future。tokio 没有依赖 crossbeam,但它的缓存行对齐取值注明抄自 crossbeam,它 2019 年以前的本地队列就是 crossbeam 的 deque;tantivy、pingora、sqlx、tauri 各卷都直接用到 crossbeam 的 channel 或队列。本卷之后是 rayon 卷。
全卷沿四条线展开:
- 一条消息:
bounded(1)上send判满、Backoff自旋、注册到SyncWaker、park;recv改写槽的 stamp、notify、CAS 选中等待者、unpark。 - 一个任务:
Worker::push写进环形缓冲、满了加倍;Stealer::steal读front、pin、读back、读任务、CAS;旧缓冲交给 epoch。 - 一块内存的回收:
epoch::pin写本地纪元、SeqCstfence;defer_destroy进本地袋子、封上全局纪元进全局队列;所有已 pin 的参与者都跟上时纪元推进,落后两个纪元的袋子被回收。 - 内存序横线:每遇到一个
Ordering,问它在和谁配对、防的是哪种重排。
flowchart TB intro[00 导读] --> overview[01 全景] overview --> mo[02 内存序与验证] mo --> utils[03 utils] utils --> epoch[04 epoch] epoch --> deque[05 deque] utils --> chan[06 channel] chan --> qs[07 queue 与 skiplist] epoch --> qs deque --> design[08 设计取舍] qs --> design design --> pit[09 常见坑] pit --> site[10 在本站中] site --> hands[11 动手]
实验环境
本机 Apple M2 Max(8 个性能核 + 4 个能效核,缓存行 128 字节),macOS,rustc 1.99.1。实验程序在 exp-crossbeam/ 下,依赖锁定在上表的版本,对照组是 std、flume、parking_lot、tokio。性能类一律 release、至少重复 3 次取中位数,注明测量时的负载;macOS 不能绑核,线程可能被调度到能效核上。每个实验都带一个反向验证。规矩的细节见 怎么读这一卷。
各部分
- 00 导读:版本与分支、四条主线、阅读路线、实验方法;crate 分层、feature 与 cfg。
- 01 全景:crossbeam 补了 std 的哪些空白;三条主线各走一遍。
- 02 内存序与验证:五类
Ordering用法;loom、Miri、TSan 和为它们多出来的 cfg。 - 03 crossbeam-utils:
CachePadded、Backoff、AtomicCell、Parker与WaitGroup、ShardedLock、作用域线程。 - 04 crossbeam-epoch:本卷重点。为什么需要内存回收;指针类型、pin、defer、回收;内部的无锁链表和队列。
- 05 crossbeam-deque:Chase-Lev、扩容与回收、
Steal::Retry与批量窃取、Injector。rayon 卷的前置。 - 06 crossbeam-channel:本卷重点。六种 flavor、
Context与Waker、select;和std::sync::mpmc逐文件对照,和 tokio mpsc、flume 对照。 - 07 queue 与 skiplist:
ArrayQueue、SegQueue;并发跳表。 - 08 设计取舍:把各章的取舍汇总到一起。
- 09 常见坑:用报错原文或现象做标题。
- 10 在本站中:本站经 tantivy、rayon、sqlx、pingora 间接依赖的 crossbeam(desktop 构建还经 tao)。
- 11 动手:最小 MPMC channel、最小 EBR。
从「导读」开始。只想用好 crossbeam 的读者,读 01、06、09;为 rayon 卷做准备的,读 03、04、05;想读懂实现的,按顺序读。