MST

星途 面试题库

面试题:Rust中原子加载与存储操作如何确保线程安全

在Rust中,原子加载与存储操作对于多线程编程至关重要。请描述原子加载(load)和存储(store)操作的基本原理,以及它们是如何协同工作来确保线程安全的?并给出一个简单的多线程示例代码,展示原子加载与存储操作的正确使用。
26.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

原子加载(load)和存储(store)操作基本原理

  1. 原子加载(load):原子加载操作从原子类型的变量中读取值。在多线程环境下,它确保读取操作是原子的,即不会被其他线程的操作中断。这意味着读取的值是在某个时刻变量的完整状态,而不是部分更新的值。
  2. 原子存储(store):原子存储操作将一个值写入原子类型的变量。同样,这个操作是原子的,它保证在写入过程中不会被其他线程干扰。其他线程在读取这个变量时,要么看到旧值,要么看到新写入的值,不会出现中间状态。

协同工作确保线程安全

原子加载和存储操作通过保证对共享变量的读写操作原子性,避免了数据竞争问题,从而确保线程安全。例如,多个线程可能同时尝试读取和修改一个共享变量,使用原子加载和存储操作,每个线程的读写操作都是完整的,不会相互干扰。

简单多线程示例代码

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

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

    for _ in 0..10 {
        let counter = Arc::clone(&shared_counter);
        let handle = thread::spawn(move || {
            // 原子存储
            counter.store(1, Ordering::SeqCst);
            // 原子加载
            let value = counter.load(Ordering::SeqCst);
            println!("Thread got value: {}", value);
        });
        handles.push(handle);
    }

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

在这个示例中,AtomicUsize 类型的 shared_counter 用于在多个线程间共享数据。每个线程通过 store 方法原子地存储值,然后通过 load 方法原子地加载值,从而保证线程安全。Ordering::SeqCst 是一种较强的内存序,确保操作按顺序执行,进一步保证线程安全。