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 日志(顺序不定)。

结合场景再看三个关注点

  1. 消息 move 到接收方
  2. 所有 sender drop 后 rx 迭代结束
  3. 同步 channel 背压 vs 异步 channel 生态差异

核心概念与准确模型

  • Sender/Receiver
  • send/recv/try_recv
  • sync_channel(bound) 有界
  • 关闭:全部 sender drop

错误:SendError/RecvError 表示对端关闭。

设计动机

  • 所有权转移 = 清晰的数据主人
  • 减少锁竞争面
  • 组合流水线

边界与误区

  • 忘记 drop 额外 sender 导致死等
  • 无界队列内存膨胀
  • 需要广播/多消费者时换生态 crate

[!warning] 常见误区:假设 mpsc 保留发送顺序跨多线程总是“全局公平” 单 sender 有序;多 sender 交织。

工程实践

  1. 明确消息类型与关闭协议
  2. 有界 channel 控背压
  3. 错误处理不要全 unwrap
  4. 复杂图用成熟库(crossbeam/tokio::sync)

本节总结

  • 消息传递转移所有权
  • mpsc 基础模型
  • 与共享状态互补

自测题

  1. 为什么示例要 drop(tx)
  2. channel 如何帮助避免数据竞争?
参考答案
  1. 否则仍有 sender 存活,rx 迭代不结束。
  2. 同时只有一个所有者持有消息数据。

延伸阅读与资料来源

资料类型支撑内容
The Book — Message Passing官方书channel
std::sync::mpsc标准库API
创建于 2026/7/15 更新于 2026/7/15