块范围内thread_local变量的用途是什么?

如果可编译的示例有助于说明问题,则为:

#include <thread>
#include <iostream>

namespace My {
    void f(int *const p) {++*p;}
}

int main()
{
    thread_local int n {42};
    std::thread t(My::f, &n);
    t.join();
    std::cout << n << "\n";
    return 0;
}

输出:43
在示例中,新线程获得了自己的n,但是(据我所知)对此没有任何兴趣,所以为什么要打扰呢?新线程自己的n有什么用吗?如果没有用,那又有什么意义呢?

当然,我认为这是有道理的。我只是不知道这是什么意思。这就是为什么我问。

如果新线程自己的n(在我看来)要在运行时由CPU进行特殊处理-可能是因为,在机器代码级别上,无法以通常的方式通过从线程的基指针的预先计算出的偏移量来访问自己的n。新线程的堆栈—那么,我们不仅浪费机器周期和电力就是没有 yield 吗?但是,即使不需要特殊处理,也没有收获!我看不到。

那么,为什么要在块范围内使用thread_local

引用
  • thread_local and other storage classes上的首选项
  • 先前的问题:when exactly is a thread_local variable declared at global scope initialized?
  • 另一个较早的问题:thread_local variables initialization
  • 另一个较早的问题:the cost of thread_local
  • 最佳答案

    我发现thread_local仅在以下三种情况下有用:

  • 如果您需要每个线程都具有唯一的资源,以使它们不必共享,互斥等即可使用所述资源。即便如此,这仅在资源很大且/或创建起来很昂贵或需要在函数调用之间保持持久(即函数内部的局部变量不足)的情况下才有用。
  • (1)的分支-当调用线程最终终止时,您可能需要特殊的逻辑才能运行。为此,可以使用在函数中创建的thread_local对象的析构函数。对于每个使用thread_local声明进入代码块的线程,该thread_local对象的析构函数都被调用一次(在线程生命周期的结尾)。
  • 对于调用它的每个唯一线程,您可能需要执行一些其他逻辑,但只能执行一次。例如,您可以编写一个函数来注册每个称为函数的唯一线程。这听起来可能很奇怪,但是我发现这种方法在管理我正在开发的库中管理垃圾收集的资源时很有用。此用法与(1)密切相关,但在构造之后不会被使用。在线程的整个生命周期中实际上都是一个哨兵对象。
  • 关于c++ - 块范围内的thread_local,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55191177/

    10-10 02:48