面试题答案
一键面试- 引入必要的库:
在Rust中,标准库提供了
Mutex
,所以我们只需要在代码开头引入std::sync::{Mutex, Arc}
。Arc
(原子引用计数)用于在多个线程间安全地共享Mutex
。use std::sync::{Mutex, Arc}; use std::thread;
- 定义全局变量并使用
Mutex
包裹: 定义一个全局变量,并用Mutex
来保护它。这里我们定义一个简单的i32
变量。static GLOBAL_DATA: Mutex<i32> = Mutex::new(0);
- 多线程操作全局变量:
创建多个线程,每个线程获取
Mutex
的锁,然后对共享数据进行读写操作。fn main() { let mut handles = vec![]; for _ in 0..10 { let data = Arc::clone(&Arc::new(GLOBAL_DATA.clone())); let handle = thread::spawn(move || { let mut num = data.lock().unwrap(); *num += 1; println!("Thread incremented value to: {}", *num); }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } let final_value = GLOBAL_DATA.lock().unwrap(); println!("Final value: {}", *final_value); }
关键步骤解释
Mutex
的定义:Mutex
用于保护共享数据,确保同一时间只有一个线程可以访问它。Mutex::new(0)
创建了一个新的Mutex
实例,并初始化其中包裹的数据为0
。Arc
的使用:Arc
是用于线程安全的引用计数指针。因为Mutex
实现了Sync
trait,所以可以使用Arc
在多个线程间共享。Arc::clone(&Arc::new(GLOBAL_DATA.clone()))
这里首先创建一个Arc
实例指向GLOBAL_DATA
,然后克隆它以便每个线程都能有自己的引用。- 获取锁:
data.lock().unwrap()
尝试获取Mutex
的锁。如果获取成功,会返回一个智能指针(MutexGuard
),通过这个指针可以安全地访问和修改共享数据。如果获取锁失败(例如另一个线程已经持有锁),lock
会阻塞当前线程直到锁可用。这里使用unwrap
是为了简单起见,如果不想在锁获取失败时直接panic,可以使用match
语句处理Err
情况。 - 线程操作完成后释放锁:
当
MutexGuard
离开作用域时,它会自动释放锁,这样其他线程就可以获取锁并访问共享数据。 - 等待所有线程完成:
在
main
函数中,handle.join().unwrap()
等待每个线程完成,确保所有线程对共享数据的操作都执行完毕,最后打印出最终的共享数据值。