MST

星途 面试题库

面试题:Rust文件I/O中的并发读取与写入

假设有多个线程需要同时读取和写入同一个文件,在Rust中如何利用标准库及相关同步机制,确保文件操作的原子性和数据一致性,避免数据竞争问题。请给出具体的代码实现框架,并简要说明同步机制的原理。
10.6万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

代码实现框架

use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let file_path = "example.txt";
    let shared_file = Arc::new(Mutex::new(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(file_path)
        .expect("Failed to open file")));

    let mut handles = Vec::new();
    for _ in 0..10 {
        let file_clone = shared_file.clone();
        let handle = thread::spawn(move || {
            let mut file = file_clone.lock().expect("Failed to lock mutex");
            // 读取文件
            let mut contents = String::new();
            file.read_to_string(&mut contents).expect("Failed to read file");
            // 写入文件
            file.write_all(b"Some new data\n").expect("Failed to write to file");
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().expect("Failed to join thread");
    }
}

同步机制原理

  1. Mutex(互斥锁)std::sync::Mutex 用于保护对共享资源(这里是文件)的访问。它确保在任何时刻只有一个线程可以获取锁并访问被保护的资源。当一个线程调用 lock 方法时,如果锁可用,它将获取锁并返回一个 MutexGuard,该 MutexGuard 实现了 DerefDerefMut 特质,因此可以像操作原始类型一样操作被保护的资源(这里是文件)。当 MutexGuard 离开作用域时,锁会自动释放,其他线程就有机会获取锁并访问资源。
  2. Arc(原子引用计数)std::sync::Arc 用于在多个线程间共享 Mutex 包裹的文件。Arc 是线程安全的引用计数智能指针,它允许在多个线程间安全地共享数据。通过克隆 Arc,每个线程都持有一个指向相同 Mutex 包裹的文件的引用,同时保持引用计数。当最后一个 Arc 实例被销毁时,被包裹的资源(Mutex 和文件)也会被销毁。这样,利用 MutexArc 的组合,就实现了对文件操作的同步,避免了数据竞争问题。