c++多線程中的利器-thread_local

我們在這裏簡單介紹一下在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

參考

http://cifangyiquan.net/programming/thread_local/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章