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

4nt*_*ine 4 concurrency multithreading channel rust

以下代码挂在迭代器中:(游乐场

#![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");
}
Run Code Online (Sandbox Code Playgroud)

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

thread 0 finished
Got: 0
Got: 1
Got: 2
thread 1 finished
thread 2 finished
Run Code Online (Sandbox Code Playgroud)

finished iterating永远不会被打印,并且该过程在操场上被中断(在本地永远挂起)。

什么原因?

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

HHK*_*HHK 7

您需要将其放置send在评论所指示的位置,因为仅当最后一个发件人被放置时该通道才会关闭。主线程的发送仅在超出函数末尾的范围时才会被删除。

您可以显drop(send)式调用或重组您的代码,以便在启动我们的接收循环之前主线程的发送超出范围,正如 Stargateur 在评论中指出的那样(游乐场)。这是优选的,因为读者可以立即清楚在哪里send被删除,而drop(send)语句很容易被错过。