Synchronization Primitives

OnceLock<T>

std::sync::OnceLock<T> is a thread-safe synchronization primitive that can be written to at most once and thereafter hands out lock-free, guard-free shared references &T to any number of concurrent threads. It supersedes std::sync::Once whenever one-time initialization also produces a value T.

Internal Synchronization Lifecycle of OnceLock<T>

OnceLock<T> combines an internal std::sync::Once state word (Incomplete, Running, Complete, Poisoned) with an UnsafeCell<MaybeUninit<T>>:

OnceLock<T> Lifecycle:

  State 0: `Incomplete` (OnceLock::new())
     |
     | Thread A calls `.get_or_init(f)` (or `.set(val)`)
     v
  State 1: `Running` (Thread A runs `f()`; concurrent callers park on OS futex queue)
     |
     +-- If `f()` succeeds: writes `T`, sets state to `Complete` (Release), wakes waiters!
     |
     +-- If `f()` panics:   sets state to `Poisoned` (or leaves uninit if fallible init)
     v
  State 2: `Complete`
     - All subsequent `.get()` / `.get_or_init()` calls execute a single atomic `Acquire`
       load and return `&T` directly with ZERO locks or guards!

Comparing OnceLock<T> and Mutex<Option<T>>

Property OnceLock<T> Mutex<Option<T>>
Return type of read access Option<&T> or &T (plain reference, no guard!) MutexGuard<'_, Option<T>> (holds lock while reading!)
Concurrent read scalability Wait-free atomic load (zero cache-line writes on read!) Serializes readers and dirties mutex cache line on every .lock()
Can value be replaced later via &self? No (write-once invariant enables returning &T without a guard) Yes (can overwrite Some(v) or reset to None)
Usable directly in static? Yes (OnceLock::new() is const fn) Yes (Mutex::new(None) is const fn)

Using OnceLock<T> for One-Time Global and Struct Initialization

use std::sync::OnceLock;
use std::thread;

#[derive(Debug)]
struct ClusterMetadata {
    cluster_id: String,
    worker_threads: usize,
}

static CLUSTER: OnceLock<ClusterMetadata> = OnceLock::new();

fn get_cluster() -> &'static ClusterMetadata {
    CLUSTER.get_or_init(|| {
        println!("  [initializing CLUSTER metadata exactly once]");
        ClusterMetadata {
            cluster_id: String::from("prod-dhaka-01"),
            worker_threads: 8,
        }
    })
}

fn main() {
    thread::scope(|s| {
        for id in 0..3 {
            s.spawn(move || {
                // All 3 threads race to call `get_cluster()`; only 1 runs the closure,
                // and all 3 receive a direct `&'static ClusterMetadata` reference!
                let meta = get_cluster();
                println!("thread #{id} sees cluster_id = {:?}", meta.cluster_id);
            });
        }
    });

    // Attempting `.set(...)` on an already initialized `OnceLock` returns `Err(val)`:
    let duplicate_attempt = CLUSTER.set(ClusterMetadata {
        cluster_id: String::from("ignored"),
        worker_threads: 1,
    });
    println!("duplicate .set() returned Err: {}", duplicate_attempt.is_err());
}
  [initializing CLUSTER metadata exactly once]
thread #0 sees cluster_id = "prod-dhaka-01"
thread #1 sees cluster_id = "prod-dhaka-01"
thread #2 sees cluster_id = "prod-dhaka-01"
duplicate .set() returned Err: true