MST

星途 面试题库

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

在Rust的多线程编程中,你需要将一个包含可变数据的结构体传递给多个线程进行操作。请说明如何使用引用和可变性来确保线程安全,并且不违反Rust的借用规则。假设结构体为`struct SharedData { value: i32 }`,每个线程可能会对`value`进行读取或修改操作。
32.9万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 使用ArcMutex

    • Arc(原子引用计数)用于在多个线程间共享数据,它允许数据有多个所有者。
    • Mutex(互斥锁)用于保护数据,确保同一时间只有一个线程可以访问数据。
    use std::sync::{Arc, Mutex};
    use std::thread;
    
    struct SharedData {
        value: i32
    }
    
    fn main() {
        let shared_data = Arc::new(Mutex::new(SharedData { value: 0 }));
        let mut handles = vec![];
    
        for _ in 0..10 {
            let data = Arc::clone(&shared_data);
            let handle = thread::spawn(move || {
                let mut data = data.lock().unwrap();
                data.value += 1;
                println!("Thread updated value: {}", data.value);
            });
            handles.push(handle);
        }
    
        for handle in handles {
            handle.join().unwrap();
        }
    }
    
  2. 解释

    • 首先,我们创建了一个Arc<Mutex<SharedData>>类型的shared_dataArc允许SharedData结构体在多个线程间共享,而Mutex确保对SharedData内部数据(即value)的访问是线程安全的。
    • 在每个线程中,我们通过data.lock().unwrap()获取对Mutex保护的数据的可变引用。lock方法会阻塞当前线程,直到获取到锁,从而确保同一时间只有一个线程可以访问SharedData
    • data.value进行操作后,我们释放了锁,其他线程就可以获取锁并进行操作。
    • 最后,我们通过join方法等待所有线程完成。
  3. 使用RwLock(如果读操作频繁)

    • RwLock(读写锁)允许多个线程同时进行读操作,但只允许一个线程进行写操作。
    use std::sync::{Arc, RwLock};
    use std::thread;
    
    struct SharedData {
        value: i32
    }
    
    fn main() {
        let shared_data = Arc::new(RwLock::new(SharedData { value: 0 }));
        let mut handles = vec![];
    
        for _ in 0..5 {
            let data = Arc::clone(&shared_data);
            let handle = thread::spawn(move || {
                let data = data.read().unwrap();
                println!("Thread read value: {}", data.value);
            });
            handles.push(handle);
        }
    
        for _ in 0..3 {
            let data = Arc::clone(&shared_data);
            let handle = thread::spawn(move || {
                let mut data = data.write().unwrap();
                data.value += 1;
                println!("Thread updated value: {}", data.value);
            });
            handles.push(handle);
        }
    
        for handle in handles {
            handle.join().unwrap();
        }
    }
    
  4. 解释

    • 这里我们使用Arc<RwLock<SharedData>>来管理共享数据。
    • 对于读操作,我们通过data.read().unwrap()获取不可变引用,允许多个线程同时读取。
    • 对于写操作,我们通过data.write().unwrap()获取可变引用,这会阻塞其他读操作和写操作,确保数据一致性。