使用Channels实现SPMC后,Rust应用发送数据无法退出求解
Rust SPMC模式程序停滞问题的原因与修复
问题根源
你的代码核心错误是销毁发送端的顺序完全反了:
- Rust的
mpscchannel接收端的for msg in &rx迭代逻辑是:只要还有对应的发送端存在,就会一直阻塞等待新消息;只有当所有发送端都被销毁时,迭代器才会结束,循环退出。 - 你现在先调用
handle_challenge_n1.join().unwrap(),主线程会一直等待子线程结束,但子线程的循环因为发送端还没销毁,永远不会退出,形成死锁。
修复后的代码
use std::sync::mpsc; use std::thread; fn main() { let (tx_n1, rx_n1) = mpsc::unbounded(); let (tx_n2, rx_n2) = mpsc::unbounded(); let handle_challenge_n1 = thread::spawn(move|| { for msg in rx_n1 { // 直接用所有权迭代更简洁,无需引用 println!("thread n1: Received {}", msg); } // 无需手动drop(rx_n1),作用域结束会自动销毁 }); let handle_challenge_n2 = thread::spawn(move|| { for msg in rx_n2 { println!("thread n2: Received {}", msg); } }); // 生产者发送所有数据 for i in 1..10 { tx_n1.send(i).unwrap(); tx_n2.send(i).unwrap(); } // 关键:先销毁所有发送端,让子线程的迭代器知道没有新消息了 drop(tx_n1); drop(tx_n2); // 等待子线程结束 handle_challenge_n1.join().unwrap(); handle_challenge_n2.join().unwrap(); println!("Main thread: Exiting.") }
额外说明
- 无需手动
drop(rx_n1):子线程结束时,rx_n1的所有权在子线程中,作用域结束会自动销毁。 - 如果你想实现真正的单生产者多消费者(多个消费者共享同一个channel),可以用
Arc<Mutex<Receiver<T>>>让多个线程共享接收端,或者使用crossbeam-channel这类第三方库提供的原生SPMC支持。
内容的提问来源于stack exchange,提问作者Sergio Giraldo
相关产品推荐
相关产品推荐

