Rust channel
std::sync::mpsc 消息传递:发送所有权、接收阻塞、多生产者与关闭语义。
#type / concept
#status / growing
#tech / dev
#resource / rust
[!info] 关联笔记
Rust channel
这个概念为什么出现
“不要通过共享内存通信,而要通过通信共享内存。”
channel 把数据的所有权发送到另一线程,降低共享可变状态。
[!abstract] 一句话理解
mpsc::channel提供发送端/接收端;send转移消息所有权;接收端迭代直到所有发送端 drop。
最小可运行示例
场景:日志收集——工作线程上报事件,主线程打印
多个 worker 发送日志字符串,主线程统一写出口。
use std::sync::mpsc;
use std::thread;
// 业务意图:多生产者上报日志,单消费者打印。
// 教学点:clone sender;recv 循环;sender drop 结束。
fn main() {
let (tx, rx) = mpsc::channel::<String>();
for i in 0..3 {
let tx = tx.clone();
thread::spawn(move || {
tx.send(format!("event from worker {i}")).unwrap();
});
}
drop(tx); // 丢掉原始 sender,否则 rx 不结束
for msg in rx {
println!("log={msg}");
}
}
建议运行:cargo run
期望:三行 worker 日志(顺序不定)。
结合场景再看三个关注点
- 消息 move 到接收方
- 所有 sender drop 后 rx 迭代结束
- 同步 channel 背压 vs 异步 channel 生态差异
核心概念与准确模型
Sender/Receiversend/recv/try_recvsync_channel(bound)有界- 关闭:全部 sender drop
错误:SendError/RecvError 表示对端关闭。
设计动机
- 所有权转移 = 清晰的数据主人
- 减少锁竞争面
- 组合流水线
边界与误区
- 忘记 drop 额外 sender 导致死等
- 无界队列内存膨胀
- 需要广播/多消费者时换生态 crate
[!warning] 常见误区:假设 mpsc 保留发送顺序跨多线程总是“全局公平” 单 sender 有序;多 sender 交织。
工程实践
- 明确消息类型与关闭协议
- 有界 channel 控背压
- 错误处理不要全 unwrap
- 复杂图用成熟库(crossbeam/tokio::sync)
本节总结
- 消息传递转移所有权
- mpsc 基础模型
- 与共享状态互补
自测题
- 为什么示例要
drop(tx)? - channel 如何帮助避免数据竞争?
参考答案
- 否则仍有 sender 存活,rx 迭代不结束。
- 同时只有一个所有者持有消息数据。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — Message Passing | 官方书 | channel |
| std::sync::mpsc | 标准库 | API |