面试题答案
一键面试1. 条件变量(Condvar
)的作用
在生产者 - 消费者模型中,Condvar
用于协调线程之间的同步。它允许一个线程(生产者)通知其他线程(消费者)有新的数据可用,同时让消费者线程在没有数据时等待,避免无效的忙碌等待,从而防止数据竞争和死锁。
2. 代码示例
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
fn main() {
let shared_data = Arc::new((Mutex::new(None), Condvar::new()));
let producer_shared_data = shared_data.clone();
// 生产者线程
let producer = thread::spawn(move || {
for i in 0..10 {
let (lock, cvar) = &*producer_shared_data;
let mut data = lock.lock().unwrap();
*data = Some(i);
println!("Produced: {}", i);
data = cvar.notify_one().unwrap();
}
});
let consumer_shared_data = shared_data.clone();
// 消费者线程
let consumer = thread::spawn(move || {
let (lock, cvar) = &*consumer_shared_data;
loop {
let mut data = lock.lock().unwrap();
while data.is_none() {
data = cvar.wait(data).unwrap();
}
let value = data.take().unwrap();
println!("Consumed: {}", value);
if value == 9 {
break;
}
}
});
producer.join().unwrap();
consumer.join().unwrap();
}
3. 关键部分解释
Arc<(Mutex<Option<i32>>, Condvar)>
:Arc
用于在多个线程间共享数据,因为它允许线程安全地克隆指针。Mutex
用于保护共享数据(这里是Option<i32>
),确保同一时间只有一个线程可以访问数据,防止数据竞争。Condvar
用于线程间的同步通知,让消费者线程在没有数据时等待,生产者线程有数据时通知消费者。
- 生产者线程:
let mut data = lock.lock().unwrap();
:获取锁,进入临界区,确保对共享数据的独占访问。*data = Some(i);
:生成数据并放入共享变量。data = cvar.notify_one().unwrap();
:通知一个等待在条件变量上的消费者线程有新数据可用。
- 消费者线程:
let mut data = lock.lock().unwrap();
:获取锁,进入临界区。while data.is_none() { data = cvar.wait(data).unwrap(); }
:如果没有数据,释放锁并等待在条件变量上,当收到通知后重新获取锁并检查数据。let value = data.take().unwrap();
:取出并消费数据。if value == 9 { break; }
:当消费完最后一个数据后,退出循环。
join
操作:producer.join().unwrap();
和consumer.join().unwrap();
等待生产者和消费者线程完成,确保主线程不会提前退出。