我們在這裏簡單介紹一下在c++11中新添加的-thread_local
我們在介紹thread_local之間首先需要說明一下什麼是線程週期,以及什麼情況下的變量可以被聲明爲thread_local相等與將一個可變數據
一.什麼是thread_local
帶有thread_local
關鍵字的變量具有線程週期,這些變量在線程開始的時候就被生成,在線程銷燬的時候就被銷燬,並且每一個線程都具有一個獨立的變量,也就是相當於每一個線程都有一份不同的變量
thread_local相當於通過將可變變量讓每一個線程都擁有獨立的副本,從而實現線程封裝的機制
和它同是存儲期的指定符還有四種
關鍵字 | 說明 |
---|---|
auto | 自動存儲期 |
register | 自動存儲期,指示編譯器會將此對象放入處理器的寄存器中 |
static | 靜態或者線程存儲期的內部連接 |
extern | 靜態或者線程存儲期的外部連接 |
thread_local | 線程存儲器 |
二.thread_local能爲我們做什麼?
通過修飾的變量有如下的特性:
- 變量在線程創建的時候進行生成
- 線程結束的時候被銷燬
- 每一個線程都擁有自己的變量副本
- thread_local 可以和static 或者extern 聯合進行使用,影響變量的連接屬性
//thread_local 測試
#include<iostream>
#include<thread>
#include<mutex>
thread_local int x = 1;
void func(){
for(int i = 0 ; i < 4; i++)
{
x++;
printf("%ld: %d\n",std::this_thread::get_id() , x);
}
}
int main()
{
std::thread t1(func);
std::thread t2(func);
t1.join();
t2.join();
return 0;
}
我們可以使用g++ xxx.cc -lpthread 來運行程序
我們可以從打印結果來清晰的看出來,每個線程都有一份自己的備份,並且是相互不干擾的
void func(){
for(int i = 0 ; i < 4; i++)
{
thread_local int x = 1;
x++;
printf("%ld: %d\n",std::this_thread::get_id() , x);
}
}
將上述函數重新進行修改
說明thread_local設置爲局部變量的話,並沒有重新進行賦值,我感覺可以將其理解爲在線程中的static變量
thread_local int i=0;
void f(int newval){
i=newval;
}
void g(){
std::cout<<i;
}
void threadfunc(int id){
f(id);
++i;
g();
}
int main(){
i=9;
std::thread t1(threadfunc,1);
std::thread t2(threadfunc,2);
std::thread t3(threadfunc,3);
t1.join();
t2.join();
t3.join();
std::cout<<i<<std::endl;
}
這代碼可能會輸出 “2349” , “3249” ,“4239” , “2439” 或者 "3429"其中每一個線程都有自己的副本 i,這些副本是完全獨立的,並且每個都有不同的地址.每一個都不相互干擾
總結
- thread_local描述的對象在thread開始的時候進行分配,thread結束的時候進行分解
- 相當於thread中的static變量
- 一般在聲明的時候進行賦值,在本thread只執行一次
- 描述的對象只在作用域中有效
- 描述類成員變量的時候,必須是static