Multithreading 如何在Rust结构内部创建线程局部变量?

Multithreading 如何在Rust结构内部创建线程局部变量?,multithreading,rust,thread-local,Multithreading,Rust,Thread Local,我需要一个线程局部变量,理想情况下存储在一个结构中,该结构当前存储程序的大部分全局状态 我能看到的第一种方法是使用thread\u local宏,但是我希望将此线程保持在状态结构中的本地 实现这一点的第二种方法是在线程和我的线程局部变量的值之间有一个HashMap或类似的值。然后我会有一个getter,它使用thread::current来查找适当的值 我应该提到的最后一个要求是,并不是给定程序中的所有线程都是由锈代码创建的,但是锈代码可以在任何线程上运行,因此解决方案应该对此具有健壮性 有没有

我需要一个线程局部变量,理想情况下存储在一个结构中,该结构当前存储程序的大部分全局状态

我能看到的第一种方法是使用
thread\u local宏,但是我希望将此线程保持在状态结构中的本地

实现这一点的第二种方法是在线程和我的线程局部变量的值之间有一个
HashMap
或类似的值。然后我会有一个getter,它使用
thread::current
来查找适当的值

我应该提到的最后一个要求是,并不是给定程序中的所有线程都是由锈代码创建的,但是锈代码可以在任何线程上运行,因此解决方案应该对此具有健壮性

有没有一种最佳实践方法可以做到这一点?也许有一个
threadId
允许我使用简单的
Vec
而不是
HashMap
(和/或避免哈希开销)?这里有图书馆吗


另一种选择是修改可在多线程上下文中使用的每个函数的参数,以同时获取状态结构和threadlocal状态结构,但是这对于不是由Rust创建的线程来说并不容易

在结构中使用线程局部变量可以通过将其放置在impl块中来完成:

use std::cell::RefCell;

struct Foo;
impl Foo {
    thread_local! {
        // Could add pub to make it public to whatever Foo already is public to.
        static FOO: RefCell<usize> = RefCell::new(0);
    }
}

但是,请注意,必须使用它前面的
Foo::
来访问它,因为它不是一个字段,而是一个关联的
static

也可以通过存储对它的引用来完成:

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

thread_local! {
    // Note lack of pub
    static FOO: RefCell<usize> = RefCell::new(0);
}
struct Bar {
    // Visibility here changes what can see `foo`.
    foo: &'static LocalKey<RefCell<usize>>,
    // Rest of your data.
}
impl Bar {
    fn constructor() -> Self {
        Self {
            foo: &FOO,
            // Rest of your data.
        }
    }
}
使用std::cell::RefCell;
使用std::thread::LocalKey;
本地线程!{
//注意缺少酒吧
静态FOO:RefCell=RefCell::new(0);
}
结构条{
//此处的可见性更改了可以看到的“foo”。
foo:&的静态LocalKey,
//剩下的数据。
}
注入棒{
fn构造函数()->Self{
自我{
foo:&foo,
//剩下的数据。
}
}
}

最简单的方法是使用:

structfoo{
线程计数器:ThreadLocal,
}
impl-Foo{
fn new()->Foo{
福{
thread_计数器:ThreadLocal::new(),
}
}
}

如果说这只在存在一个结构实例时有效,对吗?有没有一种方法可以允许多个结构实例,或者这可以作为一个单独的问题?这将适用于任意数量的结构实例。如果只需要一个结构实例,那么结构本身必须包含在线程局部变量中。第一种方法将不依赖于现有结构的实例,而第二种方法将依赖于现有结构的实例。
use std::cell::RefCell;
use std::thread::LocalKey;

thread_local! {
    // Note lack of pub
    static FOO: RefCell<usize> = RefCell::new(0);
}
struct Bar {
    // Visibility here changes what can see `foo`.
    foo: &'static LocalKey<RefCell<usize>>,
    // Rest of your data.
}
impl Bar {
    fn constructor() -> Self {
        Self {
            foo: &FOO,
            // Rest of your data.
        }
    }
}
let foo = Foo::new();
let count = foo
    .thread_counter
    .get_or(|| AtomicU64::new(START_VALUE))
    .fetch_add(1, Ordering::Relaxed);