[英]How to check if a thread has finished in Rust?
当我在 Rust 中spawn
一个线程时,我得到了一个JoinHandle
,它非常适合......加入(一个阻塞操作),而不是其他。 如何检查子线程是否已从父线程退出(即JoinHandle.join()
不会阻塞)? 如果您知道如何杀死子线程,则可以加分。
我想你可以通过创建一个通道、向孩子发送一些东西并捕获错误来做到这一点,但这似乎是不必要的复杂性和开销。
从 Rust 1.7 开始,标准库中没有 API 可以检查子线程是否已退出而没有阻塞。
一种可移植的解决方法是使用通道从孩子向父母发送消息,以表明孩子即将退出。 Receiver
有一个非阻塞的try_recv
方法。 当try_recv
确实收到一条消息时,您可以使用JoinHandle
上的join()
来检索线程的结果。
还有一些不稳定的特定于平台的扩展特性,可让您获得原始线程句柄。 然后,您必须编写特定于平台的代码来测试线程是否已退出。
如果你认为这个特性应该在 Rust 的标准库中,你可以提交一个 RFC (一定要先阅读 README!)。
如果您知道如何杀死子线程,则可以加分。
Rust 中的线程是使用本机操作系统线程实现的。 尽管操作系统可能会提供一种杀死线程的方法,但这样做并不是一个好主意,因为线程分配的资源在进程结束之前不会被清理。
这是可能的,朋友们。 使用Rust会在end或panic时丢弃的 refcounters。 100% 安全。 例子:
use std::time::Duration;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
fn main() {
// Play with this flag
let fatal_flag = true;
let do_stop = true;
let working = Arc::new(AtomicBool::new(true));
let control = Arc::downgrade(&working);
thread::spawn(move || {
while (*working).load(Ordering::Relaxed) {
if fatal_flag {
panic!("Oh, my God!");
} else {
thread::sleep(Duration::from_millis(20));
println!("I'm alive!");
}
}
});
thread::sleep(Duration::from_millis(50));
// To stop thread
if do_stop {
match control.upgrade() {
Some(working) => (*working).store(false, Ordering::Relaxed),
None => println!("Sorry, but thread died already."),
}
}
thread::sleep(Duration::from_millis(50));
// To check it's alive / died
match control.upgrade() {
Some(_) => println!("Thread alive!"),
None => println!("Thread ends!"),
}
}
要点: https ://gist.github.com/DenisKolodin/edea80f2f5becb86f718c330219178e2
在操场上: https ://play.rust-lang.org/?gist=9a0cf161ba0bbffe3824b9db4308e1fb&version=stable&backtrace=0
UPD :我创建了实现这种方法thread-control
箱: https ://github.com/DenisKolodin/thread-control
简短的答案是不可能的。 但这不是真正应该解决的问题。
如果您知道如何杀死子线程,则可以加分。
绝不
即使在支持杀死线程的语言中( 请参阅此处的 Java ),也建议不要这样做。
线程的执行通常使用显式的交互点进行编码,并且通常会隐含假设不会发生其他中断。
最令人震惊的例子当然是资源:天真的“杀死”方法是停止执行线程; 这意味着不释放任何资源。 您可能会想到记忆,这是您最不担心的事情。 相反,想象一下,所有未解锁的Mutex
将在以后创建死锁......
另一种选择是在线程中注入panic
,这将导致展开。 但是,您不能在任何时候都开始放松! 程序必须定义安全点,在这些点注入panic
可以保证是安全的(在任何其他点注入恐慌都意味着可能破坏共享对象); 如何定义这样的安全点并注入panic
在本地语言中存在一个开放的研究问题,尤其是在系统W^X
上执行的那些(其中内存页面是可写的或可执行的,但绝不是两者)。
总之,没有已知的方法可以安全地(无论是在内存方面还是在功能方面)杀死一个线程。
我觉得Arc可以用来解决这个问题如果线程退出,引用计数器减一
从 rust 1.61.0 开始,有一个is_finished
方法。
https://doc.rust-lang.org/stable/std/thread/struct.JoinHandle.html#method.is_finished
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.