thread_local使用
thread_local关键字指示对象拥有线程存储期,它能与static或extern结合,但是static不影响存储期。该对象的存储在线程开始时分配,在线程结束时释放。每个线程拥有一个对象实例。
全局变量
#include <iostream> #include <thread> #include <mutex>
thread_local int x = 0; std::mutex t1_mutex;
void print_t1() { for(int i = 0; i < 3; ++i){ x++; std::lock_guard<std::mutex> lock(t1_mutex); std::cout << std::this_thread::get_id() << " " << x << std::endl; } }
int main() { std::thread at1(print_t1); std::thread at2(print_t1); at1.join(); at2.join(); return 0; }
140636358760192 1 140636358760192 2 140636358760192 3 140636350367488 1 140636350367488 2 140636350367488 3
|
局部变量
#include <iostream> #include <thread> #include <mutex>
std::mutex t1_mutex;
void print_t1() { for(int i = 0; i < 3; ++i){ thread_local int x = 0; x++; std::lock_guard<std::mutex> lock(t1_mutex); std::cout << std::this_thread::get_id() << " " << x << std::endl; } }
int main() { std::thread at1(print_t1); std::thread at2(print_t1); at1.join(); at2.join(); return 0; }
140636358760192 1 140636358760192 2 140636358760192 3 140636350367488 1 140636350367488 2 140636350367488 3
|
thread_local的局部变量没有因为for循环作用域而重新赋值,这是因为线程存储期的变量都是和线程绑定的。可以理解为线程的static变量,不过变量的作用域依旧在本身的作用域外。(在for循环外使用x就会报错)
类成员变量
#include <iostream> #include <thread> #include <mutex>
std::mutex test_mutex;
class Test { public: Test() { std::lock_guard<std::mutex> lock(test_mutex); std::cout << "construct Test" << std::endl; } ~Test() = default;
thread_local static int cnt; };
thread_local int Test::cnt = 0;
void print_test() { Test t; for(int i = 0; i < 3; ++i){ t.cnt++; std::lock_guard<std::mutex> lock(test_mutex); std::cout << std::this_thread::get_id() << " " << t.cnt << std::endl; } }
int main() { std::thread at1(print_test); std::thread at2(print_test); at1.join(); at2.join(); return 0; }
construct Test 140108252534528 1 140108252534528 2 140108252534528 3 construct Test 140108244141824 1 140108244141824 2 140108244141824 3
|
类成员变量如果声明成thread_local一定要注意,改变量同时一定要使用static修饰。
总结
- thread_local描述的对象在thread开始时分配,在thread结束时释放。
- 一般在声明时赋值,在本thread中只执行一次。
- 描述的对象依旧只在作用域内有效。
- 描述类成员变量时,必须是s