MST

星途 面试题库

面试题:Rust中原子操作存储和加载方法的基本使用

请用Rust代码示例展示如何使用原子操作的存储(store)和加载(load)方法来实现两个线程间共享数据的安全传递,并且说明store方法中`Ordering`参数不同取值的含义。
40.4万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
use std::sync::{Arc, atomic::{AtomicU32, Ordering}};
use std::thread;

fn main() {
    let shared_data = Arc::new(AtomicU32::new(0));
    let shared_data_clone = Arc::clone(&shared_data);

    let handle = thread::spawn(move || {
        // 存储数据
        shared_data_clone.store(42, Ordering::SeqCst);
    });

    // 主线程加载数据
    let value = shared_data.load(Ordering::SeqCst);
    handle.join().unwrap();
    println!("Loaded value: {}", value);
}

Ordering参数不同取值的含义:

  1. SeqCst(顺序一致性):这是最严格的内存序。所有使用SeqCst的原子操作形成一个全序,并且这个顺序与程序中这些操作的顺序一致。它保证所有线程看到的原子操作顺序是相同的,这有助于确保复杂多线程程序的正确性,但也带来了较高的性能开销。
  2. Acquire:用于加载操作。它保证在加载操作之后的所有读/写操作不会被重排到加载操作之前。这意味着一旦一个线程通过Acquire加载了一个值,它可以确保在此之前其他线程对共享变量的所有修改都已经完成。
  3. Release:用于存储操作。它保证在存储操作之前的所有读/写操作不会被重排到存储操作之后。当一个线程使用Release存储一个值时,它确保对共享变量的修改对其他线程可见,并且在此之前的所有修改都已经完成。
  4. Relaxed:这是最宽松的内存序。它只保证原子性,不提供任何内存顺序的保证。不同线程对同一个原子变量的Relaxed操作可以以任意顺序发生,这在某些只需要保证原子性而不需要严格内存顺序的场景下可以提高性能。
  5. AcqRel:结合了AcquireRelease的语义,用于既需要加载又需要存储的操作,如fetch_add等。它保证在操作之前的所有读/写操作不会被重排到操作之后,并且在操作之后的所有读/写操作不会被重排到操作之前。