thread_local 关键字
thread_local 是 C++ 11 新引入的一种存储类型,它会影响变量的存储周期。
C++11中有如下几种存储类型:
序号 | 类型 | 备注 |
---|---|---|
1 | auto | 该关键字用于两种情况: 1. 声明变量时: 根据初始化表达式自动推断变量类型。 2. 声明函数作为函数返回值的占位符。 |
2 | static | static变量只初始化一次,除此之外它还有可见性的属性: 1. static修饰函数内的“局部”变量时,表明它不需要在进入或离开函数时创建或销毁。且仅在函数内可见。 2. static修饰全局变量时,表明该变量仅在当前(声明它的)文件内可见。 3. static修饰类的成员变量时,则该变量被该类的所有实例共享。 |
3 | register | 寄存器变量。该变量存储在CPU寄存器中,而不是RAM(栈或堆)中。该变量的最大尺寸等于寄存器的大小。由于是存储于寄存器中,因此不能对该变量进行取地址操作。 |
4 | extern | 引用一个全局变量。当在一个文件中定义了一个全局变量时,就可以在其它文件中使用extern来声明并引用该变量。 |
5 | mutable | 仅适用于类成员变量。以mutable修饰的成员变量可以在const成员函数中修改。参见上一章chan.simple.h中对mutex的使用。 |
6 | thread_local | 线程周期 |
- 有且只有 thread_local 关键字修饰的变量具有线程(thread)周期,这些变量在线程开始的时候被生成,在线程结束的时候被销毁,并且每一个线程都拥有一个独立的变量实例。
- 需要注意的一点是,如果类的成员函数内定义了 thread_local 变量,则对于同一个线程内的该类的多个对象都会共享一个变量实例,并且只会在第一次执行这个成员函数时初始化这个变量实例,这一点是跟类的静态成员变量类似的。
示例
如下代码所示
class A {
public:
A() {}
~A() {}
void test(const std::string &name) {
thread_local int count = 0;
++count;
std::cout << name << ": " << count << std::endl;
}
};
void func(const std::string &name) {
A a1;
a1.test(name);
a1.test(name);
A a2;
a2.test(name);
a2.test(name);
}
int main(int argc, char* argv[]) {
std::thread t1(func, "t1");
t1.join();
std::thread t2(func, "t2");
t2.join();
return 0;
}
输出:
t1: 1
t1: 2
t1: 3
t1: 4
t2: 1
t2: 2
t2: 3
t2: 4
总结:
- thread_local描述的对象在thread开始时分配,而在thread结束时分解。
- 一般在声明时赋值,在本thread中只执行一次。
- 描述的对象依然只在作用域内有效。
- 描述类成员变量时,必须是static的。