如何从 Rust 中的不同线程写入文件?

Fom*_*aut 6 rust

我正在尝试找到一种方法来锁定在不同线程中写入文件。正确的做法是什么?由于性能原因,当我需要写东西时,我不想一直打开和关闭文件。

我尝试的代码是:

use std::{fs, mem, thread};
use std::os::unix::prelude::FileExt;
use std::sync::{Arc, Mutex};


const COUNT: usize = 1000;


fn main() {
    let file: fs::File = fs::File::create("foo.txt").unwrap();

    let v: [u32; COUNT] = [6; COUNT];

    let counter = Arc::new(Mutex::new(0));

    let mut threads = Vec::new();
    for _ in 0..COUNT {
        let counter = Arc::clone(&counter);

        let thread = thread::spawn(move || {
            let mut i = counter.lock().unwrap();

            let offset = (mem::size_of::<u32>() * (*i)) as u64;
            let bytes = unsafe { mem::transmute::<u32, [u8; 4]>(v[*i]) };
            file.write_all_at(&bytes, offset).unwrap();

            *i += 1;
        });
        threads.push(thread);
    }

    for thread in threads {
        thread.join().unwrap();
    }
}
Run Code Online (Sandbox Code Playgroud)

它给出了错误:

move occurs because `file` has type `std::fs::File`, which does not implement the `Copy` trait
Run Code Online (Sandbox Code Playgroud)

据我了解,文件对象不能在线程之间轻松共享。我想,我在这个问题上的整个方法上做了一些错误的事情。那么在 Rust 中从不同线程写入文件的正确方法是什么?

Ibr*_*med 8

您可以将文件包装在 anArc和 a中Mutex,这将允许它在线程之间共享,并一次由一个线程进行修改:

fn main() {
    let file = Arc::new(Mutex::new(File::create("foo.txt").unwrap()));

    let v: [u32; COUNT] = [6; COUNT];

    let counter = Arc::new(Mutex::new(0));

    let mut threads = Vec::new();
    for _ in 0..COUNT {
        let counter = Arc::clone(&counter);
        let file = Arc::clone(&file);

        let thread = thread::spawn(move || {
            let mut i = counter.lock().unwrap();
            let file = file.lock().unwrap();

            let offset = (mem::size_of::<u32>() * (*i)) as u64;
            let bytes = unsafe { mem::transmute::<u32, [u8; 4]>(v[*i]) };
            file.write_all_at(&bytes, offset).unwrap();

            *i += 1;
        });
        threads.push(thread);
    }

    for thread in threads {
        thread.join().unwrap();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意, 中的读取和写入方法std::os::unix::fs::FileExt采用对 的不可变引用self。这意味着上面的代码可以在没有 的情况下编译Mutex,因为并发性是由操作系统内核管理的。但是,由于多个线程可能会尝试同时写入文件,因此结果是不确定的,这可能不是您想要的。