Appearance
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
,那就没必要进入等待状态了;否则,就进入阻塞状态,等待子线程完成任务。