thread_local變量是C++ 11新引入的一種存儲類型。它會影響變量的存儲周期(Storage duration),C++中有4種存儲周期:
- automatic
- static
- dynamic
- thread
有且只有thread_local關鍵字修飾的變量具有線程周期(thread duration),這些變量(或者說對象)在線程開始的時候被生成(allocated),在線程結束的時候被銷毀(deallocated)。並且每 一個線程都擁有一個獨立的變量實例(Each thread has its own instance of the object)。thread_local 可以和static 與 extern關鍵字聯合使用,這將影響變量的鏈接屬性(to adjust linkage)。
那么,哪些變量可以被聲明為thread_local?以下3類都是ok的
- 命名空間下的全局變量
- 類的static成員變量
- 本地變量
thread_local
int x; //A thread-local variable at namespace scope
class X
{
static thread_local std::string s; //A thread-local static class data member
};
static thread_local std::string X::s; //The definition of X::s is required
void foo()
{
thread_local std::vector<int> v; //A thread-local local variable
}
class X
{
static thread_local std::string s; //A thread-local static class data member
};
static thread_local std::string X::s; //The definition of X::s is required
void foo()
{
thread_local std::vector<int> v; //A thread-local local variable
}
既然每個線程都擁有一份獨立的thread_local變量,那么就有2個問題需要考慮:
- 各線程的thread_local變量是如何初始化的
- 各線程的thread_local變量在初始化之后擁有怎樣的生命周期,特別是被聲明為thread_local的本地變量(local variables)
下面的代碼可以幫助回答這2個問題,我的測試環境是vs2015。
輸出的前3行打印能幫助解答thread_local變量是如何初始化的,可以看到每個線程都會進行一次初始化,例子中的g_n在主線程中最早被初始化為1,隨后被修改為2和3,但這些修改操作並不影響g_n在線程t2和t3中的初始值(值為1),雖然t2和t3線程啟動的時候主線程中的變量值已經被更新為3,所以主線程、thread1、thread2打印結果分別為3,2,2。
后6行打印說明了一個事實,聲明為thread_local的本地變量在線程中是持續存在的,不同於普通臨時變量的生命周期,它具有static變量一樣的初始化特征和生命周期,雖然它並沒有被聲明為static。例子中foo函數中的thread_local變量 i 在每個線程第一次執行到的時候初始化,在每個線程各自累加,在線程結束時釋放。
#include <thread>
thread_local int g_n = 1;
void f()
{
g_n++;
printf("id=%d, n=%d\n", std::this_thread::get_id(),g_n);
}
void foo()
{
thread_local int i=0;
printf("id=%d, n=%d\n", std::this_thread::get_id(), i);
i++;
}
void f2()
{
foo();
foo();
}
int main()
{
g_n++;
f();
std::thread t1(f);
std::thread t2(f);
t1.join();
t2.join();
f2();
std::thread t4(f2);
std::thread t5(f2);
t4.join();
t5.join();
return 0;
}
thread_local int g_n = 1;
void f()
{
g_n++;
printf("id=%d, n=%d\n", std::this_thread::get_id(),g_n);
}
void foo()
{
thread_local int i=0;
printf("id=%d, n=%d\n", std::this_thread::get_id(), i);
i++;
}
void f2()
{
foo();
foo();
}
int main()
{
g_n++;
f();
std::thread t1(f);
std::thread t2(f);
t1.join();
t2.join();
f2();
std::thread t4(f2);
std::thread t5(f2);
t4.join();
t5.join();
return 0;
}
輸出(id值是每次運行時變的):
id=8004, n=3
id=8008, n=2id=8012, n=2
id=8004, n=0
id=8004, n=1
id=8016, n=0
id=8016, n=1
id=8020, n=0
id=8020, n=1
from:http://www.cnblogs.com/pop-lar/p/5123014.html
