MST

星途 面试题库

面试题:Rust线程间如何安全共享数据

在Rust中,当多个线程需要访问和修改共享数据时,为了避免数据竞争,通常会使用哪些机制?请举例说明如何使用 `Arc` 和 `Mutex` 来实现线程安全的共享数据访问。
20.7万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

在Rust中,当多个线程需要访问和修改共享数据时,为了避免数据竞争,通常会使用以下机制:

  • Mutex(互斥锁):通过互斥访问来保证同一时间只有一个线程可以访问共享数据。
  • RwLock(读写锁):允许多个线程同时进行读操作,但只允许一个线程进行写操作,在读多写少的场景下能提高性能。
  • Arc(原子引用计数):用于在多个线程间共享数据,它会记录数据的引用数量,当引用数为0时,数据会被自动释放。

以下是使用 ArcMutex 来实现线程安全的共享数据访问的示例:

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

fn main() {
    // 创建一个Arc包裹的Mutex,Mutex中包裹着i32类型的数据
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        // 克隆Arc,每个线程都持有一份Arc
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            // 尝试获取Mutex的锁
            let mut num = counter.lock().unwrap();
            // 修改共享数据
            *num += 1;
        });
        handles.push(handle);
    }

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

    // 打印最终的计数值
    println!("Result: {}", *counter.lock().unwrap());
}

在这个例子中:

  1. 首先创建了一个 Arc<Mutex<i32>> 类型的 counterArc 用于在多个线程间共享 MutexMutex 用于保护内部的 i32 数据。
  2. 使用 for 循环创建10个线程,每个线程都克隆一份 Arc
  3. 在每个线程内部,通过 lock 方法获取 Mutex 的锁,这个操作可能会失败(例如死锁),所以使用 unwrap 简单处理错误(实际应用中应更妥善处理)。获取锁后,就可以安全地修改内部的共享数据。
  4. 主线程等待所有子线程结束后,打印最终的计数值。这样就通过 ArcMutex 实现了线程安全的共享数据访问。