面试题答案
一键面试-
Ordering
参数选择:- 读取操作(加载原子计数器):对于频繁读取缓存命中次数的操作,使用
Ordering::Relaxed
即可。因为这里主要关心的是性能,Relaxed
顺序只保证原子操作本身的原子性,不保证任何内存顺序,在这种情况下已经足够,因为读取命中次数本身不需要与其他线程的操作有特定的顺序关系。 - 写入操作(存储原子计数器):当缓存更新并存储原子计数器时,为了保证数据一致性,需要使用更强的内存顺序。这里可以使用
Ordering::SeqCst
(顺序一致性)。SeqCst
是最强的内存顺序,它确保所有线程都以相同的顺序观察到所有SeqCst
操作。虽然它性能比Relaxed
差,但对于更新缓存命中次数这种需要数据一致性的操作是合适的。
- 读取操作(加载原子计数器):对于频繁读取缓存命中次数的操作,使用
-
关键代码片段:
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
fn main() {
let cache_hit_count = AtomicUsize::new(0);
// 模拟多个读取线程
let read_handles: Vec<_> = (0..10).map(|_| {
let cache_hit_count = cache_hit_count.clone();
thread::spawn(move || {
for _ in 0..100 {
let count = cache_hit_count.load(Ordering::Relaxed);
println!("Read cache hit count: {}", count);
}
})
}).collect();
// 模拟多个写入线程
let write_handles: Vec<_> = (0..5).map(|_| {
let cache_hit_count = cache_hit_count.clone();
thread::spawn(move || {
for _ in 0..50 {
cache_hit_count.fetch_add(1, Ordering::SeqCst);
println!("Incremented cache hit count");
}
})
}).collect();
for handle in read_handles {
handle.join().unwrap();
}
for handle in write_handles {
handle.join().unwrap();
}
let final_count = cache_hit_count.load(Ordering::Relaxed);
println!("Final cache hit count: {}", final_count);
}
在上述代码中:
cache_hit_count.load(Ordering::Relaxed)
用于读取缓存命中次数,采用Relaxed
顺序。cache_hit_count.fetch_add(1, Ordering::SeqCst)
用于更新缓存命中次数,采用SeqCst
顺序保证数据一致性。