面试题答案
一键面试使用Mutex
Mutex(互斥锁)用于保证同一时间只有一个线程可以访问数据,适用于读写操作都可能修改数据的场景。
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared_data = Arc::new(Mutex::new(Vec::from([1, 2, 3])));
let mut handles = vec![];
for _ in 0..3 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let mut data = data.lock().unwrap();
data.push(4);
println!("Thread modified data: {:?}", data);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let final_data = shared_data.lock().unwrap();
println!("Final data: {:?}", final_data);
}
在上述代码中,Mutex
包裹了Vec<i32>
。lock
方法获取锁,返回一个MutexGuard
,它实现了Deref
和DerefMut
,因此可以像使用原始的Vec<i32>
一样操作数据。
使用RwLock
RwLock(读写锁)允许多个线程同时进行读操作,但只允许一个线程进行写操作。适用于读操作远远多于写操作的场景,因为读操作不互斥,能提高并发性能。
use std::sync::{Arc, RwLock};
use std::thread;
fn main() {
let shared_data = Arc::new(RwLock::new(Vec::from([1, 2, 3])));
let mut read_handles = vec![];
for _ in 0..3 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let data = data.read().unwrap();
println!("Thread read data: {:?}", data);
});
read_handles.push(handle);
}
let write_handle = thread::spawn(move || {
let mut data = shared_data.write().unwrap();
data.push(4);
println!("Thread modified data: {:?}", data);
});
for handle in read_handles {
handle.join().unwrap();
}
write_handle.join().unwrap();
let final_data = shared_data.read().unwrap();
println!("Final data: {:?}", final_data);
}
这里RwLock
包裹了Vec<i32>
。读操作使用read
方法获取一个只读的锁(返回RwLockReadGuard
),写操作使用write
方法获取一个可写的锁(返回RwLockWriteGuard
)。
场景总结
- Mutex:适用于读写操作都会修改数据的场景,确保同一时间只有一个线程能访问数据,避免数据竞争。
- RwLock:适用于读多写少的场景,读操作可并发执行,写操作独占,提高整体并发性能。