MST
星途 面试题库

面试题:Rust条件变量在多线程同步中的基础应用

请描述在Rust中如何使用条件变量(`Condvar`)和互斥锁(`Mutex`)实现简单的生产者 - 消费者模型,其中生产者线程生成数字并放入共享队列,消费者线程从队列中取出数字并打印。请给出主要代码结构及关键步骤。
22.5万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 引入必要的库: 在Rust中,std::sync 库提供了 MutexCondvar
    use std::sync::{Arc, Condvar, Mutex};
    use std::thread;
    
  2. 定义共享数据结构: 定义一个共享队列来存放生产者生成的数据。
    struct SharedQueue {
        queue: Vec<i32>,
        max_size: usize,
    }
    
  3. 初始化共享数据和同步原语: 使用 Arc 来共享数据,Mutex 来保护共享数据,Condvar 用于线程间的通知。
    let shared_queue = Arc::new(SharedQueue {
        queue: Vec::new(),
        max_size: 10,
    });
    let mutex = Arc::new(Mutex::new(shared_queue));
    let condvar = Arc::new(Condvar::new());
    
  4. 生产者线程: 生产者线程生成数字并放入共享队列。如果队列已满,生产者线程等待。
    let producer = thread::spawn({
        let mutex = mutex.clone();
        let condvar = condvar.clone();
        move || {
            for i in 0..100 {
                let mut data = mutex.lock().unwrap();
                while data.queue.len() >= data.max_size {
                    data = condvar.wait(data).unwrap();
                }
                data.queue.push(i);
                condvar.notify_one();
            }
        }
    });
    
  5. 消费者线程: 消费者线程从共享队列中取出数字并打印。如果队列为空,消费者线程等待。
    let consumer = thread::spawn({
        let mutex = mutex.clone();
        let condvar = condvar.clone();
        move || {
            loop {
                let mut data = mutex.lock().unwrap();
                while data.queue.is_empty() {
                    data = condvar.wait(data).unwrap();
                }
                let num = data.queue.remove(0);
                println!("Consumed: {}", num);
                condvar.notify_one();
                if num == 99 {
                    break;
                }
            }
        }
    });
    
  6. 等待线程结束: 等待生产者和消费者线程完成任务。
    producer.join().unwrap();
    consumer.join().unwrap();
    

主要代码结构及关键步骤总结:

  1. 引入库:导入 std::sync 库中的 ArcCondvarMutex
  2. 定义共享数据结构:包含一个存放数据的 Vec 和队列最大容量。
  3. 初始化同步原语:使用 Arc 共享 Mutex 保护的共享数据,并初始化 Condvar
  4. 生产者线程:使用 Mutex 锁定共享数据,检查队列是否已满,满则通过 Condvar 等待;放入数据后通过 Condvar 通知其他线程。
  5. 消费者线程:使用 Mutex 锁定共享数据,检查队列是否为空,空则通过 Condvar 等待;取出数据并打印后通过 Condvar 通知其他线程。
  6. 等待线程结束:调用 join 方法等待生产者和消费者线程完成。