Rust Globals Thread-local Objects


A thread-local object gets initialized on its first use in a thread. And as the name suggests, each thread will get a fresh copy independent of other threads.

use std::cell::RefCell;
use std::thread;

thread_local! {
    static FOO: RefCell<f32> = RefCell::new(1.0);

// When this macro expands, `FOO` gets type `thread::LocalKey<RefCell<f32>>`.
// Side note: One of its private member is a pointer to a function which is
// responsible for returning the thread-local object. Having all its members
// `Sync` [0], `LocalKey` is also implicitly `Sync`.
// [0]: As of writing this, `LocalKey` just has 2 function-pointers as members

fn main() {
    FOO.with(|foo| {
        // `foo` is of type `&RefCell<f64>`
        *foo.borrow_mut() = 3.0;

    thread::spawn(move|| {
        // Note that static objects do not move (`FOO` is the same everywhere),
        // but the `foo` you get inside the closure will of course be different.
        FOO.with(|foo| {
            println!("inner: {}", *foo.borrow());

    FOO.with(|foo| {
        println!("main: {}", *foo.borrow());


inner: 1
main: 3