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

Zuz*_*uza 71 c++ thread-local-storage c++11

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

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

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

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

Vla*_*cow 79

根据C++标准

当thread_local应用于块作用域的变量时,如果未明确显示,则隐含存储类指定符静态

所以这意味着这个定义

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

相当于

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

然而,一个静态变量是一样的一个thread_local变量.

1使用thread_local关键字声明的所有变量都具有线程存储持续时间.这些实体的存储应持续创建它们的线程的持续时间.每个线程有一个不同的对象或引用,声明的名称的使用是指与当前线程关联的实体

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

  • @Deduplicator块作用域变量没有链接。所以你的简历是错误的。如我在帖子中所写,它们具有线程存储持续时间。实际上,它与静态存储时间相同,但适用于每个线程。 (3认同)
  • 因此,`static` 和 `extern` 并不意味着存储类,而只是连接 thread_local 变量,即使在内部作用域中也是如此。 (2认同)

Ker*_* SB 18

是的,"线程本地存储"非常类似于"全局"(或"静态存储"),只有"整个程序的持续时间"而不是"整个线程的持续时间".因此,块本地线程局部变量在第一次控件通过其声明时被初始化,但是在每个线程中单独进行,并且在线程结束时被销毁.


veh*_*kul 6

当使用时thread_local,static暗示在块范围内(参见@ Vlad的回答),请求一个类成员; 我想,这意味着名称空间范围的链接.

每9.2/6:

在类定义中,除非也声明为static,否则不应使用thread_local storage-class-specifier声明成员

回答原来的问题:

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

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

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

没有.


Dal*_*son 5

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

当您声明一个静态变量时,该变量只有一个实例。编译器/运行时系统保证它会在您实际使用之前的某个时间为您初始化,而不指定确切的时间(此处省略了一些细节。)

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

static X * pointer = new X;
Run Code Online (Sandbox Code Playgroud)

如果多个线程同时命中静态初始化代码,则可能会泄漏 X 的实例。

当您声明一个局部变量线程时,该变量可能有许多实例。您可以将它们视为在由线程 ID 索引的映射中。这意味着每个线程都会看到自己的变量副本。

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

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