MST
星途 面试题库

面试题:Rust条件变量在复杂线程同步场景中的应用

假设你正在开发一个多线程应用,其中有一组工作线程需要等待主线程发出的特定信号后才能开始工作,工作线程完成任务后又要通知主线程。请使用Rust的条件变量(Condvar)来设计并实现这个场景,阐述你的设计思路以及代码中关键部分的作用。
45.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用互斥锁(Mutex)和条件变量(Condvar):互斥锁用于保护共享状态,条件变量用于线程间的同步。主线程和工作线程通过共享的状态和条件变量进行通信。
  2. 共享状态:定义一个结构体来表示共享状态,其中包含一个布尔标志,用于指示主线程是否发出了信号,以及一个计数器,用于记录工作线程完成任务的数量。
  3. 工作线程:工作线程在启动时等待主线程的信号,信号发出后执行任务,完成任务后通知主线程。
  4. 主线程:主线程设置信号,等待工作线程完成任务。

代码实现

use std::sync::{Arc, Condvar, Mutex};
use std::thread;

// 共享状态结构体
struct SharedState {
    signal: bool,
    completed_count: u32,
}

fn main() {
    let shared_state = Arc::new((Mutex::new(SharedState {
        signal: false,
        completed_count: 0,
    }), Condvar::new()));

    let mut handles = Vec::new();
    let num_workers = 3;

    for _ in 0..num_workers {
        let shared_state_clone = shared_state.clone();
        let handle = thread::spawn(move || {
            let (lock, cvar) = &*shared_state_clone;
            let mut state = lock.lock().unwrap();

            // 等待主线程的信号
            while!state.signal {
                state = cvar.wait(state).unwrap();
            }

            // 模拟工作
            println!("Worker started working");
            thread::sleep(std::time::Duration::from_secs(1));
            println!("Worker finished working");

            state.completed_count += 1;
            cvar.notify_one();
        });
        handles.push(handle);
    }

    // 主线程设置信号
    let (lock, cvar) = &*shared_state;
    let mut state = lock.lock().unwrap();
    state.signal = true;
    cvar.notify_all();

    // 主线程等待所有工作线程完成
    while state.completed_count < num_workers as u32 {
        state = cvar.wait(state).unwrap();
    }

    for handle in handles {
        handle.join().unwrap();
    }
}

关键部分作用

  1. SharedState结构体:用于存储共享状态,signal 表示主线程是否发出信号,completed_count 记录工作线程完成任务的数量。
  2. Arc<(Mutex, Condvar)>:使用 Arc 来实现跨线程的共享所有权,Mutex 用于保护 SharedStateCondvar 用于线程间同步。
  3. 工作线程中的 while!state.signal 循环:工作线程在启动时等待主线程的信号,cvar.wait(state) 会释放锁并阻塞线程,直到收到通知。
  4. 主线程中的 state.signal = true; cvar.notify_all();:主线程设置信号并通知所有工作线程。
  5. 主线程中的 while state.completed_count < num_workers as u32 循环:主线程等待所有工作线程完成任务,cvar.wait(state) 会阻塞主线程,直到工作线程完成任务并通知。