MST

星途 面试题库

面试题:Rust引用计数在并发场景下基础应用

在Rust中,简述引用计数 `Rc` 和原子引用计数 `Arc` 的主要区别,并且举例说明在一个简单的多线程并发场景中如何使用 `Arc` 来共享数据。
10.6万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

引用计数 Rc 和原子引用计数 Arc 的主要区别

  1. 线程安全性
    • RcRc 是单线程引用计数,它不具备线程安全性。如果在多线程环境下使用 Rc,会导致未定义行为。因为 Rc 内部的引用计数操作不是原子的,在多线程同时修改引用计数时可能会出现数据竞争。
    • ArcArc 是原子引用计数,具备线程安全性。Arc 内部的引用计数操作是原子的,这意味着多个线程可以安全地共享 Arc 实例,对其引用计数的修改不会引发数据竞争。
  2. 性能
    • Rc:由于 Rc 不需要处理原子操作带来的开销,在单线程环境下,Rc 的性能会略高于 Arc
    • Arc:由于原子操作会带来额外的开销,Arc 在性能上会比 Rc 稍差一些,不过在多线程环境下,这种开销是保证线程安全所必需的。

使用 Arc 在简单多线程并发场景中共享数据的示例

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

fn main() {
    // 创建一个 Arc 包裹的数据,这里用 Mutex 来保证数据的可变性
    let shared_data = Arc::new(Mutex::new(0));

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

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

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

在这个示例中:

  1. 首先创建了一个 Arc 包裹的 MutexMutex 用于保证内部数据的线程安全可变访问。Arc 确保数据可以在多个线程间安全共享。
  2. 通过循环创建了10个线程,每个线程都克隆一份 Arc 实例。
  3. 在每个线程内部,通过获取 Mutex 的锁来修改内部的数据。
  4. 主线程等待所有线程完成后,打印最终的数据值。这样就实现了在多线程场景下安全地共享和修改数据。