面试题答案
一键面试1. 原子操作和内存屏障相关机制
- 原子操作:Rust的
std::sync::atomic
模块提供了原子类型(如AtomicBool
、AtomicUsize
等),这些类型的操作保证了原子性,即操作不可被打断。在间接延迟初始化场景下,常用于标记初始化状态。例如,用AtomicBool
标记一个值是否已经初始化。 - 内存屏障:虽然Rust没有像C++那样直接暴露内存屏障的函数,但原子操作默认会带有一定的内存屏障语义。不同的原子操作(如
load
、store
等)具有不同的内存屏障强度。例如,store
操作通常具有释放(Release)语义,load
操作通常具有获取(Acquire)语义,这有助于确保释放 - 获取顺序。
2. 示例代码
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
// 定义一个全局的原子布尔变量,用于标记是否已经初始化
static INITIALIZED: AtomicBool = AtomicBool::new(false);
// 定义一个全局的可互斥访问的变量,用于存储延迟初始化的值
static mut LAZY_VALUE: Option<Arc<Mutex<i32>>> = None;
fn get_lazy_value() -> Arc<Mutex<i32>> {
// 先检查是否已经初始化
if INITIALIZED.load(Ordering::Acquire) {
// 如果已经初始化,直接返回值
unsafe { LAZY_VALUE.as_ref().unwrap().clone() }
} else {
// 如果未初始化,进行初始化
let new_value = Arc::new(Mutex::new(42));
// 初始化完成后,设置标记为已初始化
INITIALIZED.store(true, Ordering::Release);
// 存储新值
unsafe { LAZY_VALUE = Some(new_value.clone()); }
new_value
}
}
在上述代码中:
INITIALIZED.load(Ordering::Acquire)
操作具有获取语义,确保在读取LAZY_VALUE
之前,所有之前对内存的写操作都已经完成。INITIALIZED.store(true, Ordering::Release)
操作具有释放语义,确保在设置INITIALIZED
为true
之前,对LAZY_VALUE
的赋值操作已经完成。这样就保证了释放 - 获取顺序的稳定性,使得多个线程在访问get_lazy_value
时,能正确地获取到初始化后的值。