multithreading - 为什么 Condvar 不唤醒最后一个线程?
问题描述
玩弄时我得到了意想不到的结果Condvar
。我知道我不能相信我wait()
不会早起,但在我的情况下,我的一个唤醒似乎一直缺失。鉴于此示例代码:
use std::sync::{Arc, Mutex, Condvar};
use std::{
thread,
time
};
fn main() {
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pause = time::Duration::from_secs(1);
for id in 0..10 {
let pair2 = pair.clone();
thread::spawn(move|| {
let &(ref lock, ref cvar) = &*pair2;
let lock = lock.lock().unwrap();
let _ = cvar.wait(lock).unwrap();
println!("Thread {} done!", id);
});
}
// Wait for the thread to start up.
let &(ref _lock, ref cvar) = &*pair;
for _ in 0..10 {
thread::sleep(pause);
cvar.notify_one();
}
}
我只从循环中取出前八个线程:
Thread 0 done!
Thread 1 done!
Thread 2 done!
Thread 3 done!
Thread 4 done!
Thread 5 done!
Thread 6 done!
Thread 7 done!
Thread 8 done!
如果我将第二个循环的计数增加到 11,它实际上会唤醒所有 9 个。
我已经仔细检查了两者的文档wait()
,notify_one()
但这里有什么问题并不明显。
有什么想法吗?这是一个错误还是我做错了什么?
解决方案
您的主线程不会等待工作线程完成,并且根据以下文档std::thread::spawn
:
[...] 子线程可能比父线程寿命更长(除非父线程是主线程;整个进程在主线程完成时终止)。
(重点是我的)
因为您的程序在 last 之后立即终止notify_one
,所以工作线程可能会在打印值之前被杀死。
当你循环 11 次时,在 10th 之后会有 1s 的睡眠notify_all
,这意味着最新的工作线程可能会完成它的工作。
该问题的一个常见解决方案是收集JoinHandle
s 返回的 s,并按照sn99 的回答spawn
等待它们。
推荐阅读
- python - One-hot 将一列整数编码为 NumPy 矩阵,包括缺失的索引
- ios - 如何修复一些 Xcode 13 错误,例如无法正确跳转到定义?
- node.js - 如何在 onWrite() 触发后每分钟更新 Firestore 文档上的数据?
- reactjs - 如何让我的所有单选按钮答案与 React Bootstrap 垂直排列
- reactjs - useHooks 以两种不同的方式使用
- android - 在 iOS 和 Android 之间交换 RSA 公钥
- python - 如何根据用户的要求制作 optparse 选项?
- angular - 在与屏幕交互之前,不会在其他组件中读取 mat-drawer-content 的 scrollTop 值
- python - 不和谐.py | 没有足够的值来解压
- javascript - 从 redux 更改为 redux 工具包