MST

星途 面试题库

面试题:Rust 条件变量线程唤醒机制基础

在Rust中,简述条件变量(`Condvar`)如何与互斥锁(`Mutex`)配合实现线程的唤醒机制。请举例说明`wait`和`notify`方法的使用场景及作用。
35.7万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 条件变量(Condvar)与互斥锁(Mutex)配合原理
    • 在Rust中,Condvar本身不能直接保护数据,它需要与Mutex一起使用。Mutex用于保护共享数据,确保在同一时间只有一个线程可以访问这些数据。而Condvar则用于线程间的同步,允许线程等待某个条件满足后被唤醒。
    • 当一个线程需要等待某个条件时,它首先获取Mutex的锁,然后调用Condvarwait方法。wait方法会暂时释放Mutex的锁,让其他线程有机会修改共享数据。同时,该线程会进入等待状态。当另一个线程修改了共享数据并满足等待线程所期望的条件时,它可以获取Mutex的锁(如果尚未获取),然后调用Condvarnotify系列方法(如notify_onenotify_all)来唤醒等待的线程。被唤醒的线程会重新获取Mutex的锁,然后继续执行。
  2. wait方法的使用场景及作用
    • 使用场景:常用于线程需要等待某个条件满足才能继续执行的场景。例如,在生产者 - 消费者模型中,消费者线程需要等待生产者线程生产出数据后才能消费。
    • 作用:使当前线程进入等待状态,并暂时释放它持有的Mutex锁。这样其他线程就可以获取锁并修改共享数据。当被唤醒时,线程会重新获取Mutex锁,然后继续执行。
    • 示例
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

fn main() {
    let data = Arc::new((Mutex::new(0), Condvar::new()));
    let data_clone = data.clone();

    let consumer = thread::spawn(move || {
        let (lock, cvar) = &*data_clone;
        let mut data = lock.lock().unwrap();
        while *data == 0 {
            data = cvar.wait(data).unwrap();
        }
        println!("Consumer got data: {}", *data);
    });

    let producer = thread::spawn(move || {
        let (lock, cvar) = &*data;
        let mut data = lock.lock().unwrap();
        *data = 42;
        cvar.notify_one();
    });

    consumer.join().unwrap();
    producer.join().unwrap();
}
  • 在这个例子中,消费者线程通过wait方法等待数据不为0。当生产者线程修改数据并调用notify_one后,消费者线程被唤醒,重新获取锁并继续执行。
  1. notify方法的使用场景及作用
    • notify_one
      • 使用场景:当只有一个等待线程需要被唤醒时使用。例如,在单生产者 - 单消费者模型中,生产者生产数据后,只需要唤醒一个消费者线程。
      • 作用:随机唤醒一个正在等待该Condvar的线程。
    • notify_all
      • 使用场景:当所有等待线程都需要被唤醒时使用。例如,在服务器处理一批任务后,所有等待结果的客户端线程都需要被唤醒。
      • 作用:唤醒所有正在等待该Condvar的线程。所有被唤醒的线程会竞争获取Mutex锁,获取到锁的线程会继续执行。