MST

星途 面试题库

面试题:Rust 中如何使用原子类型处理多线程进度报告中的数据一致性

在 Rust 的多线程环境下,要实现一个简单的进度报告系统,报告当前任务完成的百分比。请描述如何使用原子类型来确保不同线程对进度数据的读取和更新不会产生数据竞争,同时写出一个简单的代码示例展示基本的原子操作。
32.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 使用原子类型避免数据竞争
    • 在 Rust 中,std::sync::atomic 模块提供了原子类型,如 AtomicU32 等。原子类型保证对其值的操作是原子的,即在多线程环境下不会出现数据竞争。
    • 当多个线程需要读取和更新进度数据(例如完成任务的百分比)时,可以使用 AtomicU32 来存储这个进度值。更新操作可以使用 fetch_add 等原子方法,读取操作可以使用 load 方法。这些方法都提供了内存顺序参数,用于控制内存访问的顺序,以确保线程安全。
  2. 代码示例
use std::sync::{Arc, atomic::{AtomicU32, Ordering}};
use std::thread;

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

    for _ in 0..10 {
        let progress_clone = Arc::clone(&progress);
        let handle = thread::spawn(move || {
            for _ in 0..10 {
                // 原子地增加进度
                progress_clone.fetch_add(1, Ordering::SeqCst);
                // 原子地读取进度
                let current_progress = progress_clone.load(Ordering::SeqCst);
                println!("Thread is at progress: {}%", current_progress);
            }
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }
    let final_progress = progress.load(Ordering::SeqCst);
    println!("Final progress: {}%", final_progress);
}

在上述代码中:

  • 首先创建了一个 Arc<AtomicU32> 类型的 progressArc 用于在多个线程间共享数据,AtomicU32 确保对数据的原子操作。
  • 在每个线程中,使用 fetch_add 原子地增加进度值,并使用 load 原子地读取进度值并打印。
  • 主线程等待所有子线程完成后,读取并打印最终的进度值。