MST

星途 面试题库

面试题:Rust中Arc共享内存下的并发控制

在使用Arc实现共享内存时,如果涉及多线程并发访问,会遇到哪些问题?如何利用Rust的同步原语(如Mutex、RwLock等)来解决这些问题?请举例说明。
36.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

多线程并发访问共享内存问题

  1. 数据竞争(Data Race):多个线程同时读写共享内存,可能导致数据不一致或未定义行为。例如,一个线程读取数据的同时另一个线程修改该数据,可能读取到部分修改的数据。
  2. 竞态条件(Race Condition):线程执行顺序依赖于不确定因素,导致程序行为不可预测。比如,多个线程竞争对共享内存的初始化,可能导致初始化顺序错误。

使用Rust同步原语解决问题

  1. Mutex(互斥锁)
    • 原理:Mutex允许同一时间只有一个线程访问共享资源。当一个线程获取到锁时,其他线程必须等待锁释放才能访问。
    • 示例
use std::sync::{Arc, Mutex};

fn main() {
    let shared_data = Arc::new(Mutex::new(0));

    let mut handles = vec![];
    for _ in 0..10 {
        let data = shared_data.clone();
        let handle = std::thread::spawn(move || {
            let mut num = data.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

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

    let result = shared_data.lock().unwrap();
    println!("Final value: {}", *result);
}

在这个例子中,Arc<Mutex<i32>> 用于在多个线程间共享一个 i32 类型的数据。每个线程通过 lock 方法获取锁,修改数据后自动释放锁。

  1. RwLock(读写锁)
    • 原理:RwLock允许多个线程同时读共享资源,但只允许一个线程写。写操作需要独占锁,读操作可以并发进行,前提是没有写操作。
    • 示例
use std::sync::{Arc, RwLock};

fn main() {
    let shared_data = Arc::new(RwLock::new(0));

    let mut read_handles = vec![];
    for _ in 0..10 {
        let data = shared_data.clone();
        let handle = std::thread::spawn(move || {
            let num = data.read().unwrap();
            println!("Read value: {}", *num);
        });
        read_handles.push(handle);
    }

    let write_handle = std::thread::spawn(move || {
        let mut num = shared_data.write().unwrap();
        *num += 1;
    });

    for handle in read_handles {
        handle.join().unwrap();
    }
    write_handle.join().unwrap();

    let result = shared_data.read().unwrap();
    println!("Final value: {}", *result);
}

此例中,多个读线程可以同时读取共享数据,而写线程需要获取写锁才能修改数据,保证了数据一致性。