multithreading - Hanging in channel receiver iterator in Rust?
问题描述
The following code hangs in iterator: (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");
}
In the output we can clearly see the threads exited (so thread-local cloned senders are dropped):
thread 0 finished
Got: 0
Got: 1
Got: 2
thread 1 finished
thread 2 finished
finished iterating
is never printed and the process is interrupted in playground (hangs forever locally).
What's the reason?
PS. Loop in the threads is required (it's a simplified example of the code that is actually used) to show the real use case.
解决方案
You need to drop send
at the location indicated by your comment because the channel is only closed when the last sender is dropped. The main thread's send will only be dropped when it goes out of scope which is at the end of the function.
You can either call drop(send)
explicitly or restructure your code so that the main thread's send goes out of scope before you start our receive loop as Stargateur pointed out in the comments (playground). This is preferrable because it is immediately clear to the reader where send
is dropped while the drop(send)
statement can be easily missed.
推荐阅读
- python - 空路径与这些都不匹配 - Django 2 By Example
- azure-active-directory - AADSTS50011:指定的回复 URL 与配置的不匹配
- angular - 在 Angular 4 中使用移动手势(触摸)
- knockout.js - Slickgrid + DataView - 编辑单元格嗨
- tsql - 显示错误结果 tsql 的两列的总和
- node.js - 从另一个 lambda 函数调用的 AWS lambda 函数的响应始终为空
- python - Python selenium - 如何在多个页面上重复选择按钮 - 元素不可见
- django - 在 Django 中为单个事务启用脏读
- javascript - 使用其身份验证方法在 Firebase 上创建用户
- php - 参数化 SQL 查询和优化用户注册的 PHP 代码