面试题答案
一键面试OnceCell在多线程环境中的行为
- 延迟初始化:OnceCell允许在第一次使用时才初始化一个值,这对于一些资源开销较大的初始化操作很有用,避免不必要的启动开销。
- 线程安全:OnceCell在多线程环境下是线程安全的。多个线程同时尝试初始化OnceCell时,只有一个线程能够成功初始化,其他线程会等待初始化完成,然后获取已经初始化的值,从而避免数据竞争。
正确使用OnceCell避免数据竞争的方法
- 使用
get_or_init
方法:该方法在获取值时,如果值还未初始化,会调用传入的闭包进行初始化。闭包只在第一次调用get_or_init
且值未初始化时执行,并且是线程安全的。
多线程示例代码
use std::sync::{Arc, OnceCell};
use std::thread;
// 定义一个OnceCell来延迟初始化共享资源
static SHARED_RESOURCE: OnceCell<Arc<String>> = OnceCell::new();
fn main() {
// 创建多个线程
let mut handles = vec![];
for _ in 0..10 {
let handle = thread::spawn(|| {
// 获取共享资源
let resource = SHARED_RESOURCE.get_or_init(|| {
println!("Initializing shared resource...");
Arc::new("Shared Resource".to_string())
});
println!("Thread got: {}", resource);
});
handles.push(handle);
}
// 等待所有线程完成
for handle in handles {
handle.join().unwrap();
}
}
在上述代码中:
SHARED_RESOURCE
是一个OnceCell
类型的静态变量,用于存储共享资源。- 每个线程通过
get_or_init
方法获取共享资源。第一次调用get_or_init
时会初始化资源,后续调用则直接返回已初始化的值。 - 因为
OnceCell
是线程安全的,所以多个线程同时获取资源时不会发生数据竞争。