面试题答案
一键面试使用Mutex
结合Thread
类型安全共享数据的步骤
- 引入必要的模块:在Rust中,需要引入
std::sync::{Mutex, Thread}
模块,用于处理线程和互斥锁。 - 创建共享数据和
Mutex
:定义一个共享的数据结构,并使用Mutex
将其包裹起来,这样可以保证在同一时间只有一个线程能够访问该数据。 - 创建线程:使用
Thread::spawn
创建多个线程,每个线程在访问共享数据之前,需要先获取Mutex
的锁。 - 获取锁并访问数据:在线程内部,使用
lock
方法获取Mutex
的锁。如果锁可用,该方法会返回一个LockResult
,通过unwrap
方法可以获取到锁对象,进而访问共享数据。如果锁不可用,线程会被阻塞,直到锁被释放。 - 释放锁:当线程完成对共享数据的访问后,
Mutex
的锁会自动释放(通过Drop
trait),其他线程就有机会获取锁并访问数据。
代码示例
use std::sync::{Mutex, Thread};
fn main() {
// 创建共享数据和Mutex
let shared_data = Mutex::new(0);
let handles: Vec<_> = (0..10).map(|_| {
let data = shared_data.clone();
Thread::spawn(move || {
// 获取锁并访问数据
let mut num = data.lock().unwrap();
*num += 1;
println!("Thread incremented data to: {}", *num);
})
}).collect();
for handle in handles {
handle.join().unwrap();
}
let final_value = shared_data.lock().unwrap();
println!("Final value of shared data: {}", *final_value);
}
Mutex
的工作原理
Mutex
(互斥锁)是一种同步原语,它通过内部的一个标志位来表示锁的状态。当一个线程尝试获取锁时,Mutex
会检查这个标志位。如果标志位表示锁是空闲的,Mutex
会将标志位设置为锁定状态,并允许线程继续执行。如果标志位表示锁已经被占用,线程会被阻塞,放入一个等待队列中。当持有锁的线程释放锁时,Mutex
会将标志位设置为空闲状态,并从等待队列中唤醒一个线程,让它获取锁。
lock
方法的作用
lock
方法用于尝试获取Mutex
的锁。如果锁当前可用,lock
方法会返回一个LockResult
,其中包含一个代表锁的智能指针(MutexGuard
)。这个智能指针实现了Deref
和DerefMut
trait,因此可以像操作原始数据一样操作共享数据。当MutexGuard
离开作用域时,其Drop
实现会自动释放锁。如果锁当前不可用,lock
方法会阻塞当前线程,直到锁被释放。