有什么用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;
}
Output: 43
在示例中,新线程拥有自己的n
但(据我所知)不能用它做任何有趣的事情,那为什么还要麻烦呢?新线程是否属于自己的n
有什么用吗?如果没有用,那还有什么意义呢?
自然地,我假设有is一个点。我只是不知道这有什么意义。这就是我问的原因。
如果新线程是自己的n
想要(正如我所想的)CPU 在运行时进行特殊处理——也许是因为,在机器代码级别,人们无法访问自己的n
以正常方式通过预先计算的新线程堆栈基指针的偏移量——那么我们不仅浪费机器周期和电力而没有任何收获吗?然而,即使不需要特殊处理,仍然没有任何收获!不是我能看到的。
So why thread_local
在块范围内,好吗?
参考
- C 偏好设置thread_local和其他存储类别 https://en.cppreference.com/w/cpp/language/storage_duration
- 之前的一个问题:在全局范围内声明的 thread_local 变量到底何时被初始化? https://stackoverflow.com/q/35508133/1275653
- 另一个较早的问题:thread_local变量初始化 https://stackoverflow.com/q/43424789/1275653
- 还有一个较早的问题:thread_local 的成本 https://stackoverflow.com/q/8489819/1275653
I find thread_local
仅在三种情况下有用:
如果您需要每个线程都有一个唯一的资源,这样它们就不必共享、互斥等来使用所述资源。即便如此,这仅在资源很大和/或创建成本昂贵或需要跨函数调用持续存在时才有用(即函数内的局部变量不够)。
(1) 的一个分支 - 当调用线程最终终止时,您可能需要运行特殊的逻辑。为此,您可以使用析构函数thread_local
函数中创建的对象。这样的析构函数thread_local
每个进入代码块的线程都会调用一次对象thread_local
声明(在线程生命周期结束时)。
您可能需要为调用它的每个唯一线程执行一些其他逻辑,但仅执行一次。例如,您可以编写一个函数来注册调用函数的每个唯一线程。这可能听起来很奇怪,但我发现它可以用于管理我正在开发的库中的垃圾收集资源。该用法与(1)密切相关,但在其构造后不再使用。实际上是线程整个生命周期的哨兵对象。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)