跳到主要内容

Channel 消息传递

问题

Rust 中如何使用 Channel 进行线程间通信?有哪些 Channel 实现?

答案

标准库 mpsc

use std::sync::mpsc;
use std::thread;

fn main() {
// 创建无界通道
let (tx, rx) = mpsc::channel();

thread::spawn(move || {
tx.send("hello").unwrap();
tx.send("world").unwrap();
});

// 接收
println!("{}", rx.recv().unwrap()); // "hello"
println!("{}", rx.recv().unwrap()); // "world"
// rx.recv() → Err(发送端已 drop)
}

多生产者

let (tx, rx) = mpsc::channel();

for i in 0..5 {
let tx = tx.clone();
thread::spawn(move || {
tx.send(format!("线程 {} 发送", i)).unwrap();
});
}
drop(tx); // 释放原始发送端

for msg in rx { // 迭代接收直到所有发送端关闭
println!("{}", msg);
}

有界通道

let (tx, rx) = mpsc::sync_channel(3); // 容量 3

// 当通道满时,send 会阻塞
tx.send(1).unwrap();
tx.send(2).unwrap();
tx.send(3).unwrap();
// tx.send(4) → 阻塞,直到 rx 接收

crossbeam Channel(推荐)

crossbeam 提供更强大的 Channel 实现:

use crossbeam::channel;

// 有界通道
let (tx, rx) = channel::bounded(10);

// 无界通道
let (tx, rx) = channel::unbounded();

// select! 多通道选择
use crossbeam::channel::select;

let (tx1, rx1) = channel::unbounded();
let (tx2, rx2) = channel::unbounded();

select! {
recv(rx1) -> msg => println!("从 rx1 收到: {:?}", msg),
recv(rx2) -> msg => println!("从 rx2 收到: {:?}", msg),
default(Duration::from_secs(1)) => println!("超时"),
}

通道类型对比

特性mpsc::channelmpsc::sync_channelcrossbeam::channel
有界/无界无界有界两者都有
多生产者
多消费者✅(mpmc)
select
性能一般一般优秀

常见面试问题

Q1: 什么时候用 Channel,什么时候用 Mutex?

答案

  • Channel:任务之间传递数据、生产者-消费者模式、流水线处理
  • Mutex:多个线程需要原地修改共享数据结构

Go 的哲学:"用通信来共享内存"。Rust 两种方式都支持,根据场景选择。

Q2: mpsc 中 "mpsc" 是什么意思?

答案

Multi-Producer, Single-Consumer。标准库只支持多个发送者对应一个接收者。如果需要多消费者(mpmc),使用 crossbeam-channel。

Q3: Channel 的 send 会失败吗?

答案

会。当所有接收端已被 drop 时,send() 返回 Err(SendError)。同理,当所有发送端已被 drop 时,recv() 返回 Err(RecvError)

相关链接