使Rust线程脱离阻塞操作的标准方法是什么?

问题描述 投票:4回答:1

来自Java,我习惯了成语

while (true) {
  try {
    someBlockingOperation();
  } catch (InterruptedException e) {
    Thread.currentThread.interrupt(); // re-set the interrupted flag
    cleanup(); // whatever is necessary
    break;
  }
}

据我所知,这可以在整个JDK中用于任何可能阻塞的内容,例如从文件读取,从套接字,从队列甚至Thread.sleep()读取。

阅读Rust如何做到这一点,我发现很多看似特殊的解决方案,如miotokio。我也发现ErrorKind::Interrupted并试图通过发送ErrorKind到线程获得此SIGINT,但线程似乎立即死亡而不留下任何(后退)跟踪。

这是我使用的代码(注意:还不是很精通Rust,所以它可能看起来有点奇怪,但它运行):

use std::io;
use std::io::Read;
use std::thread;

pub fn main() {
    let sub_thread = thread::spawn(|| {
        let mut buffer = [0; 10];
        loop {
            let d = io::stdin().read(&mut buffer);
            println!("{:?}", d);
            let n = d.unwrap();
            if n == 0 {
                break;
            }
            println!("-> {:?}", &buffer[0..n]);
        }
    });

    sub_thread.join().unwrap();
}

通过“阻止操作”,我的意思是:

  • 睡觉
  • 套接字IO
  • IO文件
  • 队列IO(还不确定队列在Rust中的位置)

什么是相应的方式向一个线程发出信号,比如Java中的Thread.interrupt(),是时候打包回家了?

multithreading rust terminate
1个回答
5
投票

哪有这回事。阻止意味着阻止。

相反,您故意使用非阻塞工具。这就是像mio或者期货这样的图书馆的用武之地 - 他们处理将所有这些非阻塞的异步部分粘在一起的架构。

catch (InterruptedException e)

Rust没有例外。如果你希望处理一个失败案例,那就更好地用Result表示。

Thread.interrupt()

除了在线程中设置某个代码可能检查的标志然后抛出异常之外,这实际上没有做任何事情。你可以自己构建相同的结构。一个简单的实现:

use std::{
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc,
    },
    thread,
    time::Duration,
};

fn main() {
    let please_stop = Arc::new(AtomicBool::new(false));

    let t = thread::spawn({
        let should_i_stop = please_stop.clone();
        move || {
            while !should_i_stop.load(Ordering::SeqCst) {
                thread::sleep(Duration::from_millis(100));
                println!("Sleeping");
            }
        }
    });

    thread::sleep(Duration::from_secs(1));
    please_stop.store(true, Ordering::SeqCst);
    t.join().unwrap();
}

Sleep

据我所知,没办法打断。文档甚至说:

在Unix平台上,由于信号,此功能不会提前返回

Socket IO

您使用set_nonblocking等方法将套接字置于非阻塞模式,然后处理ErrorKind::WouldBlock

File IO

实际上并没有一种很好的跨平台方式来执行异步文件IO。大多数实现都会启动一个线程池并在那里执行阻塞操作,将数据发送到非阻塞的东西上。

Queue IO

也许你的意思是像MPSC channel,在这种情况下,你会使用像try_recv这样的工具。

也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.