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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22794382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:12:59  来源:igfitidea点击:

Are C++11 thread_local variables automatically static?

c++c++11thread-local-storage

提问by Zuza

Is there a difference between these two code segments:

这两个代码段有区别吗:

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

and

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

Backstory: originally I had a STATIC vector V (for holding some intermediate values, it gets cleared every time I enter the function) and a single-threaded program. I want to turn the program into a multithreading one, so somehow I have to get rid of this static modifier. My idea is to turn every static into thread_local and not worry about anything else? Can this approach backfire?

背景故事:最初我有一个 STATIC 向量 V(用于保存一些中间值,每次进入函数时它都会被清除)和一个单线程程序。我想把程序变成多线程程序,所以我必须以某种方式摆脱这个静态修饰符。我的想法是将每个静态都变成 thread_local 而不必担心其他任何事情?这种方法会适得其反吗?

回答by Vlad from Moscow

According to the C++ Standard

根据 C++ 标准

When thread_local is applied to a variable of block scope the storage-class-specifier static is impliedif it does not appear explicitly

当 thread_local 应用于块范围的变量时,如果没有显式出现,则隐含存储类说明符 static

So it means that this definition

所以这意味着这个定义

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

is equivalent to

相当于

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

However, a static variable is notthe same as a thread_local variable.

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

1 All variables declared with the thread_local keyword have thread storage duration. The storage for these entities shall last for the duration of the thread in which they are created. There is a distinct object or reference per thread, and use of the declared name refers to the entity associated with the current thread

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

To distinguish these variables the standard introduces a new term thread storage durationalong with static storage duration.

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

回答by Kerrek SB

Yes, "thread-local storage" is very similar to "global" (or "static storage"), only that instead of "duration of the entire program" you have "duration of the entire thread". So a block-local thread-local variable is initialized the first time control passes through its declaration, but separately within each thread, and it's destroyed when the thread ends.

是的,“线程本地存储”与“全局”(或“静态存储”)非常相似,只是您拥有“整个线程的持续时间”而不是“整个程序的持续时间”。因此,块局部线程局部变量在第一次控制通过其声明时被初始化,但在每个线程中是分开的,并且在线程结束时被销毁。

回答by vehsakul

When used with thread_local, staticis implied in block-scope (see @Vlad's answer), requied for a class member; I guess, means linkage for namespace scope.

thread_local, 一起使用时,static隐含在块范围内(请参阅@Vlad 的回答),是类成员所必需的;我猜,意味着命名空间范围的链接。

Per 9.2/6:

根据 9.2/6:

Within a class definition, a member shall not be declared with the thread_local storage-class-specifier unless also declared static

在类定义中,除非也声明为静态成员,否则不应使用 thread_local 存储类说明符声明成员

To answer the original question:

要回答原始问题:

Are C++11 thread_local variables automatically static?

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

There is no choice, except for namespace-scope variables.

除了命名空间范围的变量外,别无选择。

Is there a difference between these two code segments:

这两个代码段有区别吗:

No.

不。

回答by Dale Wilson

Thread local storage is static but it behaves quite differently from simple static storage.

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

When you declare a variable static there is exactly one instance of the variable. The compiler/runtime system guarantees that it will be initialized for you sometime before you actually use it, without specifying exactly when (some details omitted here.)

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

C++11 guarantees that this initialization will be thread safe, however before C++11 this thread safety was not guaranteed. For example

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

static X * pointer = new X;

could leak instances of X if more than one thread hit the static initialization code at the same time.

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

When you declare a variable thread local there are potentially many instances of the variable. You could think of them as being in a map that was indexed by thread-id. That means each thread sees its own copy of the variable.

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

Once again, if the variable is initialized the compiler/runtime system guarantees that this initialization will happen before the data is used and that the initialization will happen for each thread that uses the variable. The compiler also guarantees that initiation will be thread safe.

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

The thread safety guarantees means that there can be quite a bit of behind-the-scenes code to make the variable behave the way you expect it to -- especially considering that the compiler has no way of knowing ahead of time exactly how many threads will exist in your program and how many of these will touch the thread local variable.

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