use std::sync::atomic::AtomicPtr;
fn get_data() -> &'static Data {
static PTR: AtomicPtr<Data> = AtomicPtr::new(std::ptr::null_mut());
let mut p = PTR.load(Acquire);
if p.is_null() {
p = Box::into_raw(Box::new(generate_data()));
if let Err(e) = PTR.compare_exchange(
std::ptr::null_mut(), p, Release, Acquire
) {
// Safety: p comes from Box::into_raw right above,
// and wasn't shared with any other thread.
drop(unsafe { Box::from_raw(p) });
p = e;
}
}
// Safety: p is not null and points to a properly initialized value.
unsafe { &*p }
}
如果我把第一个PTR.load改成Relaxed,会有什么效果?
来自Rust Atomics and Locks,但是没有对第一个PTR.load做解释。我不太明白为什么我不能在这里使用Relaxed。
我认为发布交换保证了对象将被完全创建,所以加载操作不会得到旧的或不完整的数据。而在PTR.load(Acquire)时也会出现多个线程可能同时检测到PTR中的空指针,可能会有多个线程尝试创建并初始化Data对象。所以我不知道这里的效果。