thread_local是c++11为线程安全引进的变量声明符。
thread_local
是一个存储器指定符:
所谓存储器指定符,其作用类似命名空间,指定了变量名的存储期以及链接方式。同类型的关键字还有:
static
:静态或者线程存储期,同时指示是内部链接extern
:静态或线程存储期,同时提示是外部链接;thread_local
:线程存储期;mutable
:不影响存储期或链接
线程存储期:对象的存储在线程开始时分配,而在线程结束时解分配。每个线程拥有其自身的对象实例。唯有声明为 thread_local 的对象拥有此存储期。 thread_local 能与 static 或 extern 一同出现,以调整链接。
thread_local作为全局变量:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex _mutex;
thread_local int x = 1;
void thread_func(const std::string& thread_name) {
for (int i = 0; i < 50; i++) {
x++;
std::lock_guard<std::mutex> lock(_mutex);
std::cout << "thread[" << thread_name << "]: x = " << x << std::endl;
}
}
int main() {
std::thread t1(thread_func, "1");
std::thread t2(thread_func, "2");
t1.join();
t2.join();
return 0;
}
打印结果:
每个线程都拷贝了一份thread_local,所以它们各自互不干扰,去掉thread_local的打印如下:
两个线程共享一个全局变量,最终结果打印为101;
thread_local作为局部变量:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex _mutex; //方便多线程打印
void thread_func(const std::string& thread_name) {
for (int i = 0; i < 3; ++i) {
thread_local int x = 1; //只在每个线程创建时初始化一次
x++;
std::lock_guard<std::mutex> lock(_mutex);
std::cout << "thread[" << thread_name << "]: x = " << x << std::endl;
}
}
int main() {
std::thread t1(thread_func, "1");
std::thread t2(thread_func, "2");
t1.join();
t2.join();
return 0;
}
打印结果为:
说明x仅在线程创建的时候初始化了一次。这个让我想到了static的局部变量 。
thread_local作为类的变量:
thread_local 作为类成员变量时必须是 static 。
#include <iostream>
#include <mutex>
#include <thread>
std::mutex _mutex; //方便多线程打印
class B {
public:
B() {
std::lock_guard<std::mutex> lock(_mutex);
std::cout << "create B" << std::endl;
}
~B() {
std::lock_guard<std::mutex> lock(_mutex);
std::cout << "destroy B" << std::endl;
}
thread_local static int b_key;
int b_value = 24;
static int b_static;
};
thread_local int B::b_key = 12;
int B::b_static = 36;
void thread_func(const std::string& thread_name) {
B b;
for (int i = 0; i < 3; ++i) {
b.b_key--;
b.b_value--;
B::b_static--; // not thread safe
std::lock_guard<std::mutex> lock(_mutex);
std::cout << "thread[" << thread_name << "]: b_key:" << b.b_key << ", b_value:" << b.b_value << ", b_static:" << b.b_static << std::endl;
std::cout << "thread[" << thread_name << "]: B::key:" << B::b_key << ", b_value:" << b.b_value << ", b_static: " << B::b_static << std::endl;
}
return;
}
int main() {
std::thread t1(thread_func, "1");
std::thread t2(thread_func, "2");
t1.join();
t2.join();
return 0;
}
b_key的打印值和b_value,因为b_key是属于线程的,每个线程一份;而b_value是也是在类中定义的,每个线程一个类实例;但是b_static则是数据所有线程的;
打印结果如下:
参考博客:C/C++编程:thread_local 用法_c++ thread_local_OceanStar的学习笔记的博客-CSDN博客