在Rust的通道接收器迭代器中挂起?



以下代码挂起在迭代器中:(playground)

#![allow(unused)]
fn main() {
use std::sync::mpsc::channel;
use std::thread;

let (send, recv) = channel();
let num_threads = 3;
for i in 0..num_threads {
let thread_send = send.clone();
thread::spawn(move || {
loop { // exit condition does not matter, breaking right after the 1st iteration
&thread_send.send(i).unwrap(); // have to borrow in the loop
break;
}
println!("thread {:?} finished", i);
});
}
// drop `send` needed here (as it's cloned by all producers)?

for x in recv { // hanging
println!("Got: {}", x);
}
println!("finished iterating");
}

在输出中,我们可以清楚地看到退出的线程(因此线程本地克隆的发送者被删除):

thread 0 finished
Got: 0
Got: 1
Got: 2
thread 1 finished
thread 2 finished

finished iterating永远不会被打印,进程在playground中被中断(永远在本地挂起)。

原因是什么?

p。需要线程中的循环(这是实际使用的代码的简化示例)来显示真实的用例。

您需要在您的评论所指示的位置删除send,因为只有在删除最后一个发送者时通道才关闭。主线程的send只有在超出函数的作用域时才会被丢弃。

你可以显式调用drop(send)或重构你的代码,使主线程的发送超出范围之前,你开始我们的接收循环Stargateur指出在评论(操场)。这是可取的,因为读者可以立即清楚地看到send被删除了,而drop(send)语句很容易被遗漏。

最新更新