Rust 并发模式概览
常见并发结构:扇入扇出、工作池、背压、超时与防泄漏;线程与 async 的选择。
#type / concept
#status / growing
#tech / dev
#resource / rust
[!info] 关联笔记
Rust 并发模式概览
这个概念为什么出现
会用 spawn/channel 之后,工程失败常在结构:任务泄漏、无界队列、无超时、关闭无协议。
本篇给模式地图,不绑定单一 crate 版本细节。
[!abstract] 一句话理解 用清晰的任务生命周期、有界队列背压、超时与统一取消,把线程/async 原语组装成可运维的并发系统。
最小可运行示例
场景:有界任务队列防止内存打爆
生产者提交任务,消费者处理;有界 channel 在队列满时阻塞生产者(背压)。
use std::sync::mpsc::sync_channel;
use std::thread;
use std::time::Duration;
// 业务意图:有界队列保护内存。
// 教学点:sync_channel 背压;消费者 drop 后发送失败。
fn main() {
let (tx, rx) = sync_channel::<u32>(2);
let worker = thread::spawn(move || {
while let Ok(job) = rx.recv() {
println!("process job={job}");
}
});
for job in 1..=4 {
println!("submit {job}");
tx.send(job).unwrap();
}
drop(tx);
worker.join().unwrap();
}
建议运行:cargo run(可见 submit 与 process 交织,队列容量为 2)。
结合场景再看三个关注点
- 有界 = 背压
- 关闭协议:drop sender
- 真实系统还要超时与指标
核心模式地图
| 模式 | 要点 |
|---|---|
| 扇出 | 一任务变多任务并行 |
| 扇入 | 多结果汇聚 |
| 工作池 | 限制并发度 |
| 背压 | 有界队列/拒绝策略 |
| 超时 | 防止永久挂起 |
| 取消 | 广播关闭/CancellationToken |
| 监督 | 任务失败重启策略 |
设计动机
- 把正确性从“能跑”提升到“可长期运行”
- 明确资源上限
- 对齐运维语义(耗尽、降级)
边界与误区
- 无界 buffer “先这样” → OOM
- fire-and-forget spawn 无 join/追踪
- 混用阻塞与 async 无隔离
[!warning] 常见误区:用 sleep 假装同步协调 用条件变量/channel/通知原语。
工程实践
- 先画数据流与所有权
- 每个 spawn 有人负责生命周期
- 超时+指标默认带上
- 压测验证背压
本节总结
- 模式 > 单 API
- 背压与关闭是一等公民
- 线程/async 按负载选择
自测题
- 无界 channel 的主要风险?
- 工作池解决什么问题?
参考答案
- 内存与延迟失控。
- 限制并发,稳定资源使用。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — Concurrency | 官方书 | 基础 |
| Async Book | 社区书 | async 模式 |
| Tokio concepts | 生态 | 任务与 I/O |