thread_local變量

thread_local變量是C++ 11新引入的一種存儲類型。它會影響變量的存儲週期(Storage duration),C++中有4種存儲週期:函數

  1. automatic
  2. static
  3. dynamic
  4. thread

有且只有thread_local關鍵字修飾的變量具備線程週期(thread duration),這些變量(或者說對象)在線程開始的時候被生成(allocated),在線程結束的時候被銷燬(deallocated)。而且每 一個線程都擁有一個獨立的變量實例(Each thread has its own instance of the object)。thread_local 能夠和staticextern關鍵字聯合使用,這將影響變量的連接屬性(to adjust linkage)。測試

 

那麼,哪些變量能夠被聲明爲thread_local?如下3類都是ok的ui

  1. 命名空間下的全局變量
  2. 類的static成員變量
  3. 本地變量
下面引用《C++ Concurrency in Action》書中的例子來講明這3種狀況:
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
}

 

 

既然每一個線程都擁有一份獨立的thread_local變量,那麼就有2個問題須要考慮:this

  1. 各線程的thread_local變量是如何初始化的
  2. 各線程的thread_local變量在初始化以後擁有怎樣的生命週期,特別是被聲明爲thread_local的本地變量(local variables)

下面的代碼能夠幫助回答這2個問題,個人測試環境是vs2015。spa

輸出的前3行打印能幫助解答thread_local變量是如何初始化的,能夠看到每一個線程都會進行一次初始化,例子中的g_n在主線程中最先被初始化爲1,隨後被修改成2和3,但這些修改操做並不影響g_n在線程t2和t3中的初始值(值爲1),雖然t2和t3線程啓動的時候主線程中的變量值已經被更新爲3,因此主線程、thread一、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;
}

 

輸出(id值是每次運行時變的):
code

id=8004, n=3對象

id=8008, n=2 id=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
相關文章
相關標籤/搜索