设计思路
- 错误处理:使用Rust的
Result
枚举来处理文件操作可能出现的错误。Result
有两个变体:Ok(T)
表示操作成功,包含操作结果;Err(E)
表示操作失败,包含错误信息。
- 同步机制:
- 资源竞争:使用
Mutex
(互斥锁)来保护对文件的访问。Mutex
确保在同一时间只有一个线程可以访问文件,从而避免资源竞争。
- 死锁:为了避免死锁,需要合理安排锁的获取顺序,确保所有线程以相同的顺序获取锁。
关键代码示例
use std::fs::{self, File};
use std::io::{self, Write};
use std::sync::{Arc, Mutex};
use std::thread;
// 定义一个结构体来持有文件和互斥锁
struct FileWrapper {
file: File,
mutex: Mutex<()>,
}
impl FileWrapper {
fn new(path: &str) -> Result<Self, io::Error> {
let file = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(path)?;
Ok(Self {
file,
mutex: Mutex::new(()),
})
}
fn write_to_file(&self, data: &str) -> Result<(), io::Error> {
let _lock = self.mutex.lock().unwrap();
self.file.write_all(data.as_bytes())?;
self.file.flush()?;
Ok(())
}
fn read_from_file(&self) -> Result<String, io::Error> {
let _lock = self.mutex.lock().unwrap();
let mut contents = String::new();
self.file.read_to_string(&mut contents)?;
Ok(contents)
}
}
fn main() {
let file1 = Arc::new(FileWrapper::new("file1.txt").expect("Failed to open file1"));
let file2 = Arc::new(FileWrapper::new("file2.txt").expect("Failed to open file2"));
let file1_clone = file1.clone();
let file2_clone = file2.clone();
let handle1 = thread::spawn(move || {
file1_clone.write_to_file("Data written from thread 1").unwrap();
let data = file2_clone.read_from_file().unwrap();
println!("Data read from file2 in thread 1: {}", data);
});
let handle2 = thread::spawn(move || {
file2.write_to_file("Data written from thread 2").unwrap();
let data = file1.read_from_file().unwrap();
println!("Data read from file1 in thread 2: {}", data);
});
handle1.join().unwrap();
handle2.join().unwrap();
}
代码说明
FileWrapper
结构体:包含一个File
实例和一个Mutex
。Mutex
用于保护对File
的访问。
new
方法:用于打开文件并初始化FileWrapper
实例。
write_to_file
和read_from_file
方法:在访问文件前获取Mutex
的锁,确保同一时间只有一个线程可以访问文件。
main
函数:创建两个FileWrapper
实例,并在两个线程中分别对文件进行读写操作。通过合理的锁机制,避免了资源竞争和死锁。