Rust多线程程序阻塞无法正常结束,求修复方案
Rust多线程任务阻塞问题修复
你的代码阻塞无法正常结束的核心原因是通道发送端未被正确关闭,导致接收端一直处于阻塞等待状态:
问题分析
- 输入线程发送完100个数据后,没有关闭
in_s发送端。10个工作线程的in_r.recv()会一直阻塞,等待新数据,永远不会退出循环。 - 工作线程的
ou_s发送端未全部关闭,输出线程的ou_r.recv()会持续阻塞,无法结束计算返回结果。
修复方案
- 输入线程发送完所有数据后,主动
drop(in_s)关闭输入通道的发送端。此时所有工作线程的recv会返回Err,退出循环。 - 使用
join_all等待所有工作线程执行完毕,然后关闭ou_s的发送端。输出线程的recv收到关闭信号后,退出循环并返回计算结果。
修复后的完整代码
use crossbeam_channel::bounded; use crossbeam_utils::thread; fn worker() -> usize { thread::scope(|work| { let (in_s, in_r) = bounded(10); let (ou_s, ou_r) = bounded(10); // 输入线程:发送完数据后关闭发送端 work.spawn(move |_| { for i in 0..100 { in_s.send(i).unwrap(); } drop(in_s); // 关闭输入通道发送端,通知工作线程没有新数据了 }); // 启动10个工作线程,收集它们的JoinHandle let worker_handles: Vec<_> = (0..10) .map(|_| { let in_r = in_r.clone(); let ou_s = ou_s.clone(); work.spawn(move |_| { while let Ok(i) = in_r.recv() { ou_s.send(i + 1).unwrap(); } }) }) .collect(); // 输出线程:等待所有工作线程完成后关闭输出发送端,再计算总和 let output_handle = work.spawn(move |_| { // 先等待所有工作线程结束 for handle in worker_handles { handle.join().unwrap(); } drop(ou_s); // 关闭输出通道发送端,通知输出线程没有新结果了 let mut total = 0; while let Ok(res) = ou_r.recv() { total += res; } total }); output_handle.join().unwrap() }).unwrap() } fn main() { let total = worker(); println!("Total: {}", total); // 预期输出 5050(1+2+...+100的总和) }
关键修复点说明
drop(in_s):关闭输入通道的发送端后,所有克隆的in_r接收端在读完剩余数据后,recv会返回Err(Disconnected),工作线程的循环就会退出。- 收集工作线程的
JoinHandle并等待它们全部完成:确保所有工作线程都处理完数据并退出后,再关闭ou_s,这样输出线程能读完所有结果后正常退出。
内容的提问来源于stack exchange,提问作者Moold
相关产品推荐
相关产品推荐

