Skip to content

29.9 线程局部存储

线程局部(Thread Local)的意思是,声明的这个变量看起来是一个变量,但它实际上在每一个线程中分别有自己独立的存储地址,是不同的变量,互不干扰。在不同线程中,只能看到与当前线程相关联的那个副本,因此对它的读写无须考虑线程安全问题。

在 Rust 中,线程独立存储有两种使用方式。

  • 可以使用#[thread_local] attribute 来实现。这个功能目前在稳定版中还不支持,只能在 nightly 版本中开启#![feature(thread_local)] 功能才能使用。

  • 可以使用thread_local!宏来实现。这个功能已经在稳定版中获得支持。

示例如下:


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

fn main() {

    thread_local!{
        static FOO: RefCell<u32> = RefCell::new(1)
    };

    FOO.with(|f| {
        println!("main thread value1 {:?}", *f.borrow());
        *f.borrow_mut() = 2;
        println!("main thread value2 {:?}", *f.borrow());
    });

    let t = thread::spawn(move|| {
        FOO.with(|f| {
            println!("child thread value1 {:?}", *f.borrow());
            *f.borrow_mut() = 3;
            println!("child thread value2 {:?}", *f.borrow());
        });
    });
    t.join().ok();

    FOO.with(|f| {
        println!("main thread value3 {:?}", *f.borrow());
    });
}

thread_local!声明的变量,使用的时候要用with()方法加闭包来完成。以上代码编译、执行的结果为:


rust
main thread value1 1
main thread value2 2
child thread value1 1
child thread value2 3
main thread value3 2

我们可以看到,在主线程中将 FOO 的值修改为2,但是进入子线程后,它看到的初始值依然是1。在子线程将 FOO 的值修改为3之后回到主线程,主线程看到的值还是2

这说明,在子线程中和主线程中看到的 FOO 其实是两个完全独立的变量,互不影响。

Released under the MIT License