面试题答案
一键面试在Rust中,当多个线程需要访问和修改共享数据时,为了避免数据竞争,通常会使用以下机制:
- Mutex(互斥锁):通过互斥访问来保证同一时间只有一个线程可以访问共享数据。
- RwLock(读写锁):允许多个线程同时进行读操作,但只允许一个线程进行写操作,在读多写少的场景下能提高性能。
- Arc(原子引用计数):用于在多个线程间共享数据,它会记录数据的引用数量,当引用数为0时,数据会被自动释放。
以下是使用 Arc
和 Mutex
来实现线程安全的共享数据访问的示例:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
// 创建一个Arc包裹的Mutex,Mutex中包裹着i32类型的数据
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
// 克隆Arc,每个线程都持有一份Arc
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
// 尝试获取Mutex的锁
let mut num = counter.lock().unwrap();
// 修改共享数据
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
// 打印最终的计数值
println!("Result: {}", *counter.lock().unwrap());
}
在这个例子中:
- 首先创建了一个
Arc<Mutex<i32>>
类型的counter
,Arc
用于在多个线程间共享Mutex
,Mutex
用于保护内部的i32
数据。 - 使用
for
循环创建10个线程,每个线程都克隆一份Arc
。 - 在每个线程内部,通过
lock
方法获取Mutex
的锁,这个操作可能会失败(例如死锁),所以使用unwrap
简单处理错误(实际应用中应更妥善处理)。获取锁后,就可以安全地修改内部的共享数据。 - 主线程等待所有子线程结束后,打印最终的计数值。这样就通过
Arc
和Mutex
实现了线程安全的共享数据访问。