MST

星途 面试题库

面试题:Rust中如何利用原子操作初步实现延迟初始化

在Rust中,简述使用原子操作实现延迟初始化的基本步骤,并且举例说明如何使用`std::sync::Once`和原子类型来完成一个简单的延迟初始化场景,比如延迟初始化一个全局变量。
20.7万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

使用原子操作实现延迟初始化的基本步骤

  1. 定义原子变量:使用std::sync::atomic模块中的原子类型,如AtomicBoolAtomicPtr等,来标记初始化状态。
  2. 初始化逻辑:编写实际的初始化逻辑,该逻辑可能会涉及到一些复杂的计算或者资源分配。
  3. 原子操作:使用原子操作(如compare_and_swap)来确保初始化只发生一次,避免竞争条件。

示例:使用std::sync::Once和原子类型完成延迟初始化全局变量

use std::sync::{Once, AtomicPtr};
use std::mem;

// 定义一个全局原子指针
static mut GLOBAL_VARIABLE: *const i32 = 0 as *const i32;
static INIT: Once = Once::new();

fn get_global_variable() -> &'static i32 {
    INIT.call_once(|| {
        let value = 42;
        let boxed = Box::new(value);
        unsafe {
            GLOBAL_VARIABLE = Box::into_raw(boxed);
        }
    });
    unsafe {
        &*GLOBAL_VARIABLE
    }
}

在这个例子中:

  1. GLOBAL_VARIABLE是一个全局的原子指针,初始化为空指针。
  2. INIT是一个Once类型的静态变量,用于确保初始化只执行一次。
  3. get_global_variable函数在第一次调用时,会通过INIT.call_once执行初始化逻辑,创建一个值为42i32,并将其地址存储在GLOBAL_VARIABLE中。后续调用get_global_variable时,直接返回已初始化的值。

另外,更简洁地使用OnceCell(从Rust 1.52.0开始可用)实现延迟初始化全局变量:

use std::sync::OnceCell;

static GLOBAL_VARIABLE: OnceCell<i32> = OnceCell::new();

fn get_global_variable() -> &'static i32 {
    GLOBAL_VARIABLE.get_or_init(|| {
        42
    })
}

这里OnceCell内部封装了原子操作,get_or_init方法会在变量未初始化时执行初始化闭包,确保初始化只发生一次,并且代码更加简洁。