面试题答案
一键面试互斥锁(Mutex)的使用场景
- 多线程访问共享资源:当多个线程需要访问和修改同一份数据时,为了避免数据竞争(data race)导致未定义行为,使用互斥锁来确保同一时间只有一个线程能访问该共享资源。例如,多个线程可能都需要对一个全局计数器进行增减操作,此时就需要用互斥锁来保护计数器。
- 共享可变状态:在程序中存在共享的可变数据结构,且需要在不同线程间安全地访问和修改时,互斥锁是常用的手段。比如一个共享的哈希表,不同线程可能会向其中插入或读取数据,就需要通过互斥锁来保证数据的一致性。
代码示例
use std::sync::{Mutex, Arc};
use std::thread;
fn main() {
// 创建一个被互斥锁包裹的共享数据
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
// 尝试获取互斥锁,这是一个阻塞操作,如果锁被其他线程持有,会等待
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
// 打印最终的计数器值
println!("Result: {}", *counter.lock().unwrap());
}
在上述代码中:
- 首先创建了一个被
Mutex
包裹的counter
,类型为Arc<Mutex<i32>>
。Arc
用于在多个线程间共享所有权,Mutex
用于保护内部的i32
数据。 - 通过循环创建10个线程,每个线程尝试获取
Mutex
的锁,成功获取锁后对counter
进行加1操作。 - 主线程等待所有子线程完成后,获取锁并打印最终的
counter
值。这样通过Mutex
确保了counter
在多线程环境下的安全访问和修改。