如何冻结线程并从另一个线程通知它?

时间:2016-06-22 09:51:38

标签: multithreading rust wait notify

我需要暂停Rust中的当前线程并从另一个线程通知它。在Java中我会写:

synchronized(myThread) {
    myThread.wait();
}

并从第二个线程(恢复主线程):

synchronized(myThread){
    myThread.notify();
}

可以在Rust中做同样的事吗?

4 个答案:

答案 0 :(得分:6)

使用发送类型()的频道可能最简单:

use std::sync::mpsc::channel;
use std::thread;

let (tx,rx) = channel();

// Spawn your worker thread, giving it `send` and whatever else it needs
thread::spawn(move|| {
    // Do whatever
    tx.send(()).expect("Could not send signal on channel.");
    // Continue
});

// Do whatever
rx.recv().expect("Could not receive from channel.");
// Continue working

()类型是因为它实际上是零信息,这意味着很明显你只是将它用作信号。事实上,它的大小为零意味着它在某些情况下也可能更快(但实际上可能不比正常的机器字写入更快)。

如果您只是需要通知程序线程已完成,您可以获取其加入保护并等待其加入。

let guard = thread::spawn( ... ); // This will automatically join when finished computing

guard.join().expect("Could not join thread");

答案 1 :(得分:2)

在Rust中有多种方法可以实现这一点。

Java中的底层模型是每个对象都包含互斥锁和条件变量,如果我没记错的话。因此,使用互斥锁和condition variable将起作用...

...但是,我会亲自切换到使用频道:

  • "等待" thread具有通道的接收端,并等待它
  • "通知" thread具有通道的发送端,并发送消息

操作比条件变量更容易,特别是因为在锁定变量时不会意外使用不同的互斥锁。

std::sync::mpsc有两个通道(异步和同步),具体取决于您的需求。在这里,异步匹配更紧密:std::sync::mpsc::channel

答案 2 :(得分:2)

您可以使用std::thread::park()std::thread::Thread::unpark()来实现此目标。

在你想要等待的帖子中,

fn worker_thread() {
    std::thread::park();
}

在控制线程中,已经有一个线程句柄

fn main_thread(worker_thread: std::thread::Thread) {
    worker_thread.unpark();
}

请注意,停车线程可以虚假唤醒,这意味着线程有时可以在没有任何其他线程调用unpark的情况下唤醒。您应该在代码中为这种情况做好准备,或使用@ Jsor答案中建议的std::sync::mpsc::channel之类的内容。

答案 3 :(得分:1)

有一个monitor箱子通过在便利结构中将MutexCondvar相结合来提供此功能。

(完全披露:我是作者。)

简而言之,它可以像这样使用:

    let mon = Arc::new(Monitor::new(false));
    {
        let mon = mon.clone();
        let _ = thread::spawn(move || {
            thread::sleep(Duration::from_millis(1000));

            mon.with_lock(|mut done| {     // done is a monitor::MonitorGuard<bool>
                *done = true;
                done.notify_one();
            });
        });
    }

    mon.with_lock(|mut done| {
        while !*done {
            done.wait();
        }
        println!("finished waiting");
    });

此处,mon.with_lock(...)在语义上等同于Java synchronized(mon) {...}