如何检查线程是否已完成Rust?

时间:2016-03-09 05:11:02

标签: multithreading rust

当我在Rust中spawn一个线程时,我得到一个JoinHandle,这对于...加入(阻塞操作)很有用,而不是其他。如何从父线程检查子线程是否已退出(即JoinHandle.join()不会阻塞)?如果您知道如何杀死子线程,则可获得奖励。

我想你可以通过创建一个频道,向孩子发送内容,捕捉错误来做到这一点,但这似乎是不必要的复杂性和开销。

4 个答案:

答案 0 :(得分:9)

从Rust 1.7开始,标准库中没有API来检查子线程是否已经退出而没有阻塞。

便携式解决方法是使用channels从孩子向父母发送消息,以表示孩子即将退出。 Receiver有一种非阻塞try_recv方法。当try_recv收到邮件时,您可以使用join()上的JoinHandle来检索帖子的结果。

还有一些不稳定的特定于平台的扩展特性,可以让您获取原始线程句柄。然后,您必须编写特定于平台的代码来测试该线程是否已退出。

如果您认为此功能应该在Rust的标准库中,您可以submit an RFC(请务必先阅读README!)。

  

如果您知道如何杀死子线程,则获得积分。

Rust中的线程是使用本机OS线程实现的。即使操作系统可能提供了一种杀死线程的方法,这样做是个坏主意,因为在进程之前,线程分配的资源不会被清除>结束。

答案 1 :(得分:9)

简短的回答是不可能的。但这不是应该真正解决的问题。

  

如果您知道如何杀死子线程,则获得积分。

<强> NEVER

即使在支持杀死线程(see Java here)的语言中,也不建议使用。

线程的执行通常用显式交互点编码,并且通常存在隐式假设,不会发生其他中断。

最令人震惊的例子当然是资源:天真的&#34;杀人&#34;方法是停止执行线程;这意味着不会释放任何资源。你可能会考虑记忆,这是你最不担心的事情。相反,想象一下,所有未解锁的Mutex会在以后创建死锁......

另一种选择是在线程中注入panic,这将导致展开。但是,你不能只是在任何时候开始放松!该程序必须定义安全点,注入panic将保证安全(在任何其他点注入它意味着可能破坏共享对象);如何定义这样的安全点并注入panic在本地语言中存在一个开放的研究问题,特别是那些在系统W^X上执行的问题(其中内存页面是可写的或可执行的但从不两者都有)。

总之,没有已知的安全方法(内存方式和功能方面)杀死线程。

答案 2 :(得分:4)

有可能,朋友们。使用 refcounters ,Rust会在结束恐慌时放弃。 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 crate来实现这种方法:https://github.com/DenisKolodin/thread-control

答案 3 :(得分:0)

我认为可以用Arc解决这个问题 如果线程退出,则参考计数器减一。