Rust标准库中的线程局部变量如何工作?

时间:2019-11-19 20:15:55

标签: multithreading rust thread-local thread-local-storage

Rust标准库中的thread local variables如何工作?我看着the code,但间接地迷路了。线程本地存储,操作系统依赖模式和快速模式似乎有不同的配置。默认是哪一个,我该如何选择使用哪一个?尤其是,在板条箱中使用线程本地存储对板条箱的用户有什么意义?

使用线程本地存储非常简单,generated assembly看起来确实很有效,但是如果不完全理解其含义,就无法在库中使用该功能。

我还问过:

1 个答案:

答案 0 :(得分:9)

您看到的不同配置与#[thread_local]有关,此功能旨在替换thread_local!宏,以使用户代码更简单明了,例如:

#![feature(thread_local)]

#[thread_local]
pub static mut VAR: u64 = 42;

但是,在撰写本文时,此功能尚未完全实现(您可以找到跟踪问题here)。但是,它在编译器代码中内部使用了 ,这就是您在实际的“快速” implementation in std::thread::LocalKey中看到的魔力:

#[thread_local]
#[cfg(all(
    target_thread_local,
    not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
))]
static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
    $crate::thread::__FastLocalKeyInner::new();

请注意顶部的#[thread_local]属性。然后将其向下转换为LLVM IR,因此TLS(线程本地存储)的实际实现是carried by LLVM并实现ELF TLS models。这是默认配置。

如何选择要使用的那个?

您需要编译自己的rustc版本,而忽略target_thread_local功能。在这种情况下,将使用std::thread::LocalKey中的os variant,然后根据平台的不同,它可以使用pthreads (Unix)Windows API或其他方式。

WebAssembly是一个特例:由于它不支持线程,因此TLS将转换为简单的静态变量。