面试题答案
一键面试设计思路
- 原子类型选择:使用
AtomicUsize
来处理共享的无符号整数数据。AtomicUsize
提供了原子操作,确保在多线程环境下数据访问的原子性。 - 顺序选择:
- 写操作:对于写操作,使用
Ordering::Release
顺序。这保证了在释放存储之前,所有对该存储的写入操作都对其他线程可见。 - 读操作:对于读操作,使用
Ordering::Acquire
顺序。这确保了在获取存储之后,所有对该存储的读取操作都能看到之前线程写入的最新值。
- 写操作:对于写操作,使用
- 使用场景:当一个线程修改共享数据(写操作)并希望其他线程能够看到最新值时,使用
Release
顺序。当一个线程需要读取共享数据并确保获取到最新值时,使用Acquire
顺序。
核心代码片段
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
fn main() {
let shared_data = AtomicUsize::new(0);
let mut handles = vec![];
// 写线程
for _ in 0..5 {
let shared_data_clone = shared_data.clone();
let handle = thread::spawn(move || {
for i in 0..100 {
shared_data_clone.store(i, Ordering::Release);
}
});
handles.push(handle);
}
// 读线程
for _ in 0..5 {
let shared_data_clone = shared_data.clone();
let handle = thread::spawn(move || {
for _ in 0..100 {
let value = shared_data_clone.load(Ordering::Acquire);
println!("Read value: {}", value);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
在上述代码中,多个写线程通过store
方法以Ordering::Release
顺序更新共享数据,多个读线程通过load
方法以Ordering::Acquire
顺序读取共享数据,以此避免数据竞争并提升性能。