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的

  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個問題需要考慮:

  1. 各線程的thread_local變量是如何初始化的
  2. 各線程的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;
}

 

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM