MST
星途 面试题库

面试题:Rust闭包在多线程并发场景下的数据所有权与借用

假设有一个多线程程序,主线程创建一个闭包并传递给子线程执行,闭包中需要访问主线程中的某个数据。请说明如何确保数据所有权的正确转移和借用,以保证并发安全,同时避免数据竞争。给出具体的代码示例并解释其原理。
12.7万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

在 Rust 中,可以使用 Arc(原子引用计数)和 Mutex(互斥锁)来实现数据所有权的正确转移和借用,确保并发安全并避免数据竞争。以下是具体的代码示例及原理解释:

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

fn main() {
    // 使用 Arc 和 Mutex 包装主线程中的数据
    let data = Arc::new(Mutex::new(42));

    // 创建子线程,并将数据的 Arc 克隆一份传递给子线程
    let data_clone = data.clone();
    let handle = thread::spawn(move || {
        // 尝试获取 Mutex 的锁,如果成功,返回一个 MutexGuard,它实现了 Deref 可以像普通引用一样访问数据
        let mut data = data_clone.lock().unwrap();
        *data += 1;
        println!("子线程修改后的数据: {}", data);
    });

    // 主线程继续执行
    let mut data = data.lock().unwrap();
    *data += 1;
    println!("主线程修改后的数据: {}", data);

    // 等待子线程结束
    handle.join().unwrap();
}

原理解释

  1. ArcArc 用于在多个线程间共享数据,它通过原子引用计数确保数据在所有引用都被释放时才被销毁。这里使用 Arc 包装 Mutex 包裹的数据,使得主线程和子线程可以安全地共享这份数据。
  2. MutexMutex 提供了互斥访问机制,确保同一时间只有一个线程可以访问被保护的数据。lock 方法尝试获取锁,如果锁可用则返回一个 MutexGuard,这个 MutexGuard 在其生命周期内持有锁,当 MutexGuard 离开作用域时,锁会自动释放。
  3. 数据所有权和借用:通过 Arc::clone 方法克隆 Arc 指针,使得主线程和子线程各自持有一个指向相同数据的 Arc 实例。闭包中使用 move 关键字,确保 data_clone 的所有权被转移到子线程中。同时,通过 Mutex 的锁机制,保证在同一时间只有一个线程能访问和修改数据,从而避免数据竞争。