Appearance
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 其实是两个完全独立的变量,互不影响。