C ++ 11 thread_local变量是否自动静态?

时间:2014-04-01 18:49:37

标签: c++ c++11 thread-local-storage

这两个代码段之间是否存在差异:

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

Backstory:最初我有一个STATIC向量V(用于保存一些中间值,每次进入函数时都会被清除)和一个单线程程序。我想把程序变成多线程程序,所以我不得不摆脱这个静态修饰符。我的想法是将每个静态转换为thread_local并且不担心其他任何事情?这可能会适得其反吗?

4 个答案:

答案 0 :(得分:74)

根据C ++标准

  

当thread_local应用于块范围的变量时   存储类说明符静态隐含如果没有出现   明确地

所以这意味着这个定义

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

相当于

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

但是,静态变量与thread_local变量相同。

  

1使用thread_local关键字声明的所有变量都有线程   储存期限。这些实体的存储应该持续存储   创建它们的线程的持续时间。有一个独特的   每个线程的对象或引用,并使用声明的名称引用   与当前线程关联的实体

为了区分这些变量,标准引入了新术语 线程存储持续时间 以及静态存储持续时间。

答案 1 :(得分:16)

是,&#34;线程本地存储&#34;非常类似于&#34;全球&#34; (或&#34;静态存储&#34;),而不是整个节目的持续时间&#34;你有&#34;整个线程的持续时间&#34;。所以一个块本地线程局部变量在第一次控件通过它的声明时被初始化,但是在每个线程中分别被初始化,并且当线程结束时它被销毁。

答案 2 :(得分:5)

当与thread_local一起使用时,static隐含在块范围内(请参阅@ Vlad的回答),请求类成员;我想,这意味着名称空间范围的链接。

按9.2 / 6:

  

在类定义中,   除非也声明为static

,否则不应使用thread_local storage-class-specifier声明成员

回答原来的问题:

  

C ++ 11 thread_local变量是否自动静态?

除名称空间范围变量外没有其他选择。

  

这两个代码段之间是否存在差异:

没有

答案 3 :(得分:4)

线程本地存储是静态的,但它的行为与简单的静态存储完全不同。

当您声明一个变量static时,只有一个变量实例。编译器/运行时系统保证在您实际使用它之前将它初始化,而不确切地指定何时(这里省略了一些细节。)

C ++ 11保证这个初始化是线程安全的,但是在C ++ 11之前,这个线程的安全性并不能保证。例如

static X * pointer = new X;
如果多个线程同时触及静态初始化代码,

可能会泄漏X的实例。

当您声明一个变量线程本地时,可能存在许多变量实例。您可以将它们视为位于由thread-id索引的地图中。这意味着每个线程都会看到自己的变量副本。

再一次,如果变量被初始化,编译器/运行时系统将保证在使用数据之前进行初始化,并且对于使用该变量的每个线程都将进行初始化。编译器还保证启动是线程安全的。

线程安全保证意味着可以有相当多的幕后代码使变量按照您期望的方式运行 - 特别是考虑到编译器无法提前知道如何程序中将存在许多线程,其中有多少线程将触及线程局部变量。