Skip to content

29.7 Condvar

Condvar 是条件变量,它可以用于等待某个事件的发生。在等待的时候,这个线程处于阻塞状态,并不消耗 CPU 资源。 在常见的操作系统上,Condvar 的内部实现是调用的操作系统提供的条件变量。它调用wait方法的时候需要一个 MutexGuard 类型的参数,因此 Condvar 总是与 Mutex 配合使用的。 而且我们一定要注意,一个 Condvar 应该总是对应一个 Mutex,不可混用,否则会导致执行阶段的 panic。

Condvar 的一个常见使用模式是和一个Mutex<bool>类型结合使用。 我们可以用 Mutex 中的 bool 变量存储一个旧的状态,在条件发生改变的时候修改它的状态。 通过这个状态值,我们可以决定是否需要执行等待事件的操作。示例如下:


rust
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
use std::time::Duration;
fn main() {
    let pair = Arc::new((Mutex::new(false), Condvar::new()));
    let pair2 = pair.clone();

    thread::spawn(move|| {
        thread::sleep(Duration::from_secs(1));
        let &(ref lock, ref cvar) = &*pair2;
        let mut started = lock.lock().unwrap();
        *started = true;
        cvar.notify_one();
        println!("child thread {}", *started);
    });


    // wait for the thread to start up
    let &(ref lock, ref cvar) = &*pair;
    let mut started = lock.lock().unwrap();

    println!("before wait {}", *started);
    while !*started {
        started = cvar.wait(started).unwrap();
    }
    println!("after wait {}", *started);
}

这段代码中存在两个线程之间的共享变量,包括一个 Condvar 和一个 Mutex 封装起来的 bool 类型。我们用 Arc 类型把它们包起来。在子线程中,我们做完了某件工作之后,就将共享的 bool 类型变量设置为true,并使用Condvar::notify_one通知事件发生。

在主线程中,我们首先判定这个 bool 变量是否为true:如果已经是true,那就没必要进入等待状态了;否则,就进入阻塞状态,等待子线程完成任务。

Released under the MIT License