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?
背景:最初我有一个静态向量V(用于保存一些中间值,每次我输入函数时它都会被清除)和一个单线程程序。我想把程序转换成多线程的,所以我必须摆脱这个静态修饰符。我的想法是把每个静态都转换成thread_local,而不用担心其他的事情?这种方法可能适得其反?
4 个解决方案
#1
61
According to the C++ Standard
按照c++标准
When thread_local is applied to a variable of block scope the storage-class-specifier static is implied if it does not appear explicitly
当将thread_local应用到块作用域的变量时,如果不显式地显示,则表示存储类说明符静态
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 not the 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
使用thread_local关键字声明的所有变量都有线程存储时间。这些实体的存储将持续到创建它们的线程的持续时间。每个线程都有一个不同的对象或引用,声明名称的使用指的是与当前线程关联的实体
To distinguish these variables the standard introduces a new term thread storage duration along with static storage duration.
为了区分这些变量,标准引入了新的术语线程存储持续时间和静态存储持续时间。
#2
10
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.
是的,“线程本地存储”与“全局存储”(或“静态存储”)非常相似,只是您有“整个线程的持续时间”而不是“整个程序的持续时间”。因此,块本地线程局部变量在第一次控件通过声明时被初始化,但在每个线程中都是单独的,并且在线程结束时被销毁。
#3
4
When used with thread_local
, static
is implied in block-scope (see @Vlad's answer), requied for a class member; I guess, means linkage for namespace scope.
当与thread_local一起使用时,block-scope中隐含了静态(参见@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.
不。
#4
3
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.
线程安全保障意味着可以有相当多的幕后代码以使变量按照你希望的方式运作,尤其是考虑到提前编译器没有办法知道究竟有多少线程将存在于您的程序和有多少个线程局部变量会联系。
#1
61
According to the C++ Standard
按照c++标准
When thread_local is applied to a variable of block scope the storage-class-specifier static is implied if it does not appear explicitly
当将thread_local应用到块作用域的变量时,如果不显式地显示,则表示存储类说明符静态
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 not the 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
使用thread_local关键字声明的所有变量都有线程存储时间。这些实体的存储将持续到创建它们的线程的持续时间。每个线程都有一个不同的对象或引用,声明名称的使用指的是与当前线程关联的实体
To distinguish these variables the standard introduces a new term thread storage duration along with static storage duration.
为了区分这些变量,标准引入了新的术语线程存储持续时间和静态存储持续时间。
#2
10
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.
是的,“线程本地存储”与“全局存储”(或“静态存储”)非常相似,只是您有“整个线程的持续时间”而不是“整个程序的持续时间”。因此,块本地线程局部变量在第一次控件通过声明时被初始化,但在每个线程中都是单独的,并且在线程结束时被销毁。
#3
4
When used with thread_local
, static
is implied in block-scope (see @Vlad's answer), requied for a class member; I guess, means linkage for namespace scope.
当与thread_local一起使用时,block-scope中隐含了静态(参见@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.
不。
#4
3
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.
线程安全保障意味着可以有相当多的幕后代码以使变量按照你希望的方式运作,尤其是考虑到提前编译器没有办法知道究竟有多少线程将存在于您的程序和有多少个线程局部变量会联系。