Synchronization Primitives

LazyLock<T>

std::sync::LazyLock<T, F = fn() -> T> is a thread-safe lazy initialization primitive that bundles an initialization function F directly into the container at construction time (LazyLock::new(|| ...)) and executes it automatically on the first dereference (*lazy or LazyLock::force(&lazy)).

How LazyLock<T, F> Combines Once with a Union of F and T

Internally, LazyLock<T, F> stores a std::sync::Once state word alongside a union holding either the uncalled initializer ManuallyDrop<F> (before initialization) or the initialized value ManuallyDrop<T> (after initialization). When the first thread dereferences the LazyLock:

  1. The Once lock ensures only one thread runs F.
  2. F is moved out of the union and invoked (f()), dropping any captured state in F.
  3. The resulting T is written into the union, and all subsequent Deref accesses return &T via a fast atomic load.
LazyLock<T, F> Memory Layout Transition:

  Before First Dereference:            After First Dereference:
  +----------------------------+       +----------------------------+
  | once: Once (Incomplete)    | ----> | once: Once (Complete)      |
  | data: Union::Func(f: F)    |       | data: Union::Value(val: T) |
  +----------------------------+       +----------------------------+

Choosing Between LazyLock<T> and OnceLock<T>

Question Use LazyLock<T> Use OnceLock<T>
Is the initialization logic known at static declaration time? Yes (static TABLE: LazyLock<...> = LazyLock::new(|| ...);) No (depends on CLI args or config file loaded in main())
How do callers access the value? Transparently via Deref (TABLE.get("key"), &*TABLE) Explicitly via .get() -> Option<&T> or .get_or_init(|| ...)
Can initialization fail and be retried later? No (if closure panics, LazyLock is poisoned) Yes (check condition before calling .set(val))

Using LazyLock<T> for Thread-Safe Static Caches and Regex/Lookup Tables

use std::collections::HashMap;
use std::sync::LazyLock;
use std::thread;

static STATUS_MESSAGES: LazyLock<HashMap<u16, &'static str>> = LazyLock::new(|| {
    println!("  [building STATUS_MESSAGES table on first access]");
    HashMap::from([
        (200, "OK"),
        (404, "Not Found"),
        (500, "Internal Server Error"),
    ])
});

fn format_response(code: u16) -> String {
    // Dereferences `STATUS_MESSAGES` directly as `&HashMap<u16, &'static str>`:
    let reason = STATUS_MESSAGES.get(&code).copied().unwrap_or("Unknown");
    format!("HTTP/1.1 {code} {reason}")
}

fn main() {
    // Optionally force initialization during startup warm-up, or let first worker trigger it:
    thread::scope(|s| {
        s.spawn(|| println!("{}", format_response(200)));
        s.spawn(|| println!("{}", format_response(404)));
    });
}
  [building STATUS_MESSAGES table on first access]
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found