MST

星途 面试题库

面试题:Rust中原子类型在并发操作下如何避免数据竞争

请阐述在Rust中使用原子类型进行并发操作时,怎样利用原子类型的方法(如`fetch_add`等)来避免数据竞争,并且结合一个简单的多线程场景代码示例说明。
34.4万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

在Rust中,原子类型(std::sync::atomic模块中的类型)提供了对共享数据进行无锁操作的能力,从而避免数据竞争。这些原子类型的方法(如fetch_add)是线程安全的,因为它们使用了底层硬件提供的原子指令。

以下是一个简单的多线程场景代码示例,展示了如何使用AtomicUsizefetch_add方法来避免数据竞争:

use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

fn main() {
    let counter = AtomicUsize::new(0);
    let mut handles = vec![];

    for _ in 0..10 {
        let counter_clone = counter.clone();
        let handle = thread::spawn(move || {
            for _ in 0..1000 {
                counter_clone.fetch_add(1, Ordering::SeqCst);
            }
        });
        handles.push(handle);
    }

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

    println!("Final counter value: {}", counter.load(Ordering::SeqCst));
}

在这个示例中:

  1. 我们创建了一个AtomicUsize类型的counter,初始值为0。
  2. 使用thread::spawn创建了10个线程,每个线程对counter执行1000次fetch_add操作。fetch_add方法以原子方式增加counter的值,并返回旧值。
  3. Ordering::SeqCst是一种内存序,它提供了最强的内存一致性保证。在实际应用中,可以根据需求选择更宽松的内存序以提高性能。
  4. 主线程等待所有子线程完成,然后打印最终的counter值。

通过使用原子类型和其提供的方法,我们确保了多个线程对共享数据的并发操作是线程安全的,避免了数据竞争。