面试题答案
一键面试use std::sync::OnceCell;
// 自定义结构体
struct MyStruct {
data: i32,
}
// 线程安全的懒初始化静态变量
static MY_STRUCT: OnceCell<MyStruct> = OnceCell::new();
fn get_my_struct() -> &'static MyStruct {
MY_STRUCT.get_or_init(|| {
println!("Initializing MyStruct...");
MyStruct { data: 42 }
})
}
机制解释
-
OnceCell:
- 线程安全:
OnceCell
利用了内部的UnsafeCell
和spin::Once
来实现线程安全。UnsafeCell
允许内部可变性,而spin::Once
确保初始化只发生一次。在多线程环境下,当多个线程同时尝试初始化OnceCell
时,spin::Once
会保证只有一个线程能够执行初始化操作,其他线程会等待,从而实现线程安全。 - 懒加载:
OnceCell
实现懒加载是通过get_or_init
方法。只有在第一次调用get_or_init
时,才会执行初始化闭包,后续调用直接返回已经初始化的值,避免了不必要的初始化开销,提高了性能。
- 线程安全:
-
Lazy:
- 线程安全:
Lazy
也是线程安全的,它基于Once
和UnsafeCell
实现。在多线程环境下,Once
确保初始化操作只执行一次,从而保证线程安全。 - 懒加载:
Lazy
类型的变量在首次使用时才会进行初始化,通过延迟初始化,避免了程序启动时不必要的初始化开销,实现了懒加载特性。使用时通过Lazy::force
方法获取值,该方法会在首次调用时初始化并返回值,后续调用直接返回已初始化的值。
- 线程安全:
在Rust中,OnceCell
和 Lazy
都能很好地实现线程安全的懒初始化,OnceCell
更轻量级,适用于简单场景;Lazy
则提供了更多的功能和灵活性,例如可以在初始化时进行复杂的操作。