MST

星途 面试题库

面试题:Rust引用与可变性在多线程环境下的运用

在多线程Rust程序中,有一个共享的数据结构`SharedData`,其中包含一些可变状态。你需要创建多个线程,部分线程读取数据,部分线程修改数据。请阐述如何通过合理使用引用与可变性,结合`Mutex`、`Arc`等类型来确保线程安全,并给出具体的代码实现,解释每一步的作用。
40.2万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

线程安全思路

  1. 使用Arc: Arc(原子引用计数)用于在多个线程间共享数据,它提供了引用计数功能,确保数据在所有引用被释放时才会被销毁。由于Arc是线程安全的,所以适合在多线程环境下使用。
  2. 使用Mutex: Mutex(互斥锁)用于保护共享数据,确保在同一时间只有一个线程可以访问数据。线程在访问共享数据前需要先获取Mutex的锁,访问结束后释放锁。

代码实现

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

// 定义共享数据结构
struct SharedData {
    value: i32,
}

fn main() {
    // 创建Arc<Mutex<SharedData>>实例
    let shared_data = Arc::new(Mutex::new(SharedData { value: 0 }));

    let mut handles = vec![];

    // 创建3个读线程
    for _ in 0..3 {
        let data = Arc::clone(&shared_data);
        let handle = thread::spawn(move || {
            let data = data.lock().unwrap();
            println!("Read value: {}", data.value);
        });
        handles.push(handle);
    }

    // 创建2个写线程
    for _ in 0..2 {
        let data = Arc::clone(&shared_data);
        let handle = thread::spawn(move || {
            let mut data = data.lock().unwrap();
            data.value += 1;
            println!("Write value: {}", data.value);
        });
        handles.push(handle);
    }

    // 等待所有线程结束
    for handle in handles {
        handle.join().unwrap();
    }
}

代码解释

  1. 定义SharedData: 定义了包含可变状态value的共享数据结构。
  2. 创建Arc<Mutex<SharedData>>: 使用ArcMutex来包装SharedData,使它可以在多线程间安全共享并保护其内部数据。
  3. 创建读线程: 克隆Arc并传递给新线程,在新线程中通过lock方法获取锁,从而安全地读取SharedData中的数据。
  4. 创建写线程: 同样克隆Arc传递给新线程,获取锁后对SharedData中的数据进行修改,由于获取了锁,不会出现数据竞争问题。
  5. 等待线程结束: 使用join方法等待所有线程执行完毕,确保程序不会在所有线程结束前退出。