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