我正在尝试找到一种方法来锁定在不同线程中写入文件。正确的做法是什么?由于性能原因,当我需要写东西时,我不想一直打开和关闭文件。
我尝试的代码是:
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 中从不同线程写入文件的正确方法是什么?
您可以将文件包装在 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,因为并发性是由操作系统内核管理的。但是,由于多个线程可能会尝试同时写入文件,因此结果是不确定的,这可能不是您想要的。
| 归档时间: |
|
| 查看次数: |
3563 次 |
| 最近记录: |