MST

星途 面试题库

面试题:Rust非作用域互斥体在多线程数据共享场景中的应用

请描述在Rust中,如何使用非作用域互斥体(`Mutex`)来安全地在多线程之间共享数据。假设你有一个全局变量,多个线程需要对其进行读写操作,给出相应的代码示例并解释关键步骤。
42.5万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 引入必要的库: 在Rust中,标准库提供了Mutex,所以我们只需要在代码开头引入std::sync::{Mutex, Arc}Arc(原子引用计数)用于在多个线程间安全地共享Mutex
    use std::sync::{Mutex, Arc};
    use std::thread;
    
  2. 定义全局变量并使用Mutex包裹: 定义一个全局变量,并用Mutex来保护它。这里我们定义一个简单的i32变量。
    static GLOBAL_DATA: Mutex<i32> = Mutex::new(0);
    
  3. 多线程操作全局变量: 创建多个线程,每个线程获取Mutex的锁,然后对共享数据进行读写操作。
    fn main() {
        let mut handles = vec![];
        for _ in 0..10 {
            let data = Arc::clone(&Arc::new(GLOBAL_DATA.clone()));
            let handle = thread::spawn(move || {
                let mut num = data.lock().unwrap();
                *num += 1;
                println!("Thread incremented value to: {}", *num);
            });
            handles.push(handle);
        }
        for handle in handles {
            handle.join().unwrap();
        }
        let final_value = GLOBAL_DATA.lock().unwrap();
        println!("Final value: {}", *final_value);
    }
    

关键步骤解释

  1. Mutex的定义Mutex用于保护共享数据,确保同一时间只有一个线程可以访问它。Mutex::new(0)创建了一个新的Mutex实例,并初始化其中包裹的数据为0
  2. Arc的使用Arc是用于线程安全的引用计数指针。因为Mutex实现了Sync trait,所以可以使用Arc在多个线程间共享。Arc::clone(&Arc::new(GLOBAL_DATA.clone()))这里首先创建一个Arc实例指向GLOBAL_DATA,然后克隆它以便每个线程都能有自己的引用。
  3. 获取锁data.lock().unwrap()尝试获取Mutex的锁。如果获取成功,会返回一个智能指针(MutexGuard),通过这个指针可以安全地访问和修改共享数据。如果获取锁失败(例如另一个线程已经持有锁),lock会阻塞当前线程直到锁可用。这里使用unwrap是为了简单起见,如果不想在锁获取失败时直接panic,可以使用match语句处理Err情况。
  4. 线程操作完成后释放锁: 当MutexGuard离开作用域时,它会自动释放锁,这样其他线程就可以获取锁并访问共享数据。
  5. 等待所有线程完成: 在main函数中,handle.join().unwrap()等待每个线程完成,确保所有线程对共享数据的操作都执行完毕,最后打印出最终的共享数据值。