鍍金池/ 教程/ C/ A.8 線程本地變量
3.4 本章總結(jié)
6.3 基于鎖設(shè)計(jì)更加復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
6.1 為并發(fā)設(shè)計(jì)的意義何在?
5.2 <code>C++</code>中的原子操作和原子類型
A.7 自動(dòng)推導(dǎo)變量類型
2.1 線程管理的基礎(chǔ)
8.5 在實(shí)踐中設(shè)計(jì)并發(fā)代碼
2.4 運(yùn)行時(shí)決定線程數(shù)量
2.2 向線程函數(shù)傳遞參數(shù)
第4章 同步并發(fā)操作
2.3 轉(zhuǎn)移線程所有權(quán)
8.3 為多線程性能設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)
6.4 本章總結(jié)
7.3 對(duì)于設(shè)計(jì)無(wú)鎖數(shù)據(jù)結(jié)構(gòu)的指導(dǎo)建議
關(guān)于這本書(shū)
A.1 右值引用
2.6 本章總結(jié)
D.2 &lt;condition_variable&gt;頭文件
A.6 變參模板
6.2 基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu)
4.5 本章總結(jié)
A.9 本章總結(jié)
前言
第10章 多線程程序的測(cè)試和調(diào)試
5.4 本章總結(jié)
第9章 高級(jí)線程管理
5.1 內(nèi)存模型基礎(chǔ)
2.5 識(shí)別線程
第1章 你好,C++的并發(fā)世界!
1.2 為什么使用并發(fā)?
A.5 Lambda函數(shù)
第2章 線程管理
4.3 限定等待時(shí)間
D.3 &lt;atomic&gt;頭文件
10.2 定位并發(fā)錯(cuò)誤的技術(shù)
附錄B 并發(fā)庫(kù)的簡(jiǎn)單比較
5.3 同步操作和強(qiáng)制排序
A.8 線程本地變量
第8章 并發(fā)代碼設(shè)計(jì)
3.3 保護(hù)共享數(shù)據(jù)的替代設(shè)施
附錄D C++線程庫(kù)參考
第7章 無(wú)鎖并發(fā)數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
D.7 &lt;thread&gt;頭文件
D.1 &lt;chrono&gt;頭文件
4.1 等待一個(gè)事件或其他條件
A.3 默認(rèn)函數(shù)
附錄A 對(duì)<code>C++</code>11語(yǔ)言特性的簡(jiǎn)要介紹
第6章 基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
封面圖片介紹
7.2 無(wú)鎖數(shù)據(jù)結(jié)構(gòu)的例子
8.6 本章總結(jié)
8.1 線程間劃分工作的技術(shù)
4.2 使用期望等待一次性事件
8.4 設(shè)計(jì)并發(fā)代碼的注意事項(xiàng)
D.5 &lt;mutex&gt;頭文件
3.1 共享數(shù)據(jù)帶來(lái)的問(wèn)題
資源
9.3 本章總結(jié)
10.3 本章總結(jié)
10.1 與并發(fā)相關(guān)的錯(cuò)誤類型
D.4 &lt;future&gt;頭文件
3.2 使用互斥量保護(hù)共享數(shù)據(jù)
9.1 線程池
1.1 何謂并發(fā)
9.2 中斷線程
4.4 使用同步操作簡(jiǎn)化代碼
A.2 刪除函數(shù)
1.3 C++中的并發(fā)和多線程
1.4 開(kāi)始入門
第5章 C++內(nèi)存模型和原子類型操作
消息傳遞框架與完整的ATM示例
8.2 影響并發(fā)代碼性能的因素
7.1 定義和意義
D.6 &lt;ratio&gt;頭文件
A.4 常量表達(dá)式函數(shù)
7.4 本章總結(jié)
1.5 本章總結(jié)
第3章 線程間共享數(shù)據(jù)

A.8 線程本地變量

線程本地變量允許程序中的每個(gè)線程都有一個(gè)獨(dú)立的實(shí)例拷貝??梢允褂?code>thread_local關(guān)鍵字來(lái)對(duì)這樣的變量進(jìn)行聲明。命名空間內(nèi)的變量,靜態(tài)成員變量,以及本地變量都可以聲明成線程本地變量,為了在線程運(yùn)行前對(duì)這些數(shù)據(jù)進(jìn)行存儲(chǔ)操作:

thread_local int x;  // 命名空間內(nèi)的線程本地變量

class X
{
  static thread_local std::string s;  // 線程本地的靜態(tài)成員變量
};
static thread_local std::string X::s;  // 這里需要添加X(jué)::s

void foo()
{
  thread_local std::vector<int> v;  // 一般線程本地變量
}

由命名空間或靜態(tài)數(shù)據(jù)成員構(gòu)成的線程本地變量,需要在線程單元對(duì)其進(jìn)行使用進(jìn)行構(gòu)建。有些實(shí)現(xiàn)中,會(huì)將對(duì)線程本地變量的初始化過(guò)程,放在線程中去做;還有一些可能會(huì)在其他時(shí)間點(diǎn)做初始化,在一些有依賴的組合中,根據(jù)具體情況來(lái)進(jìn)行決定。將沒(méi)有構(gòu)造好的線程本地變量傳遞給線程單元使用,不能保證它們會(huì)在線程中進(jìn)行構(gòu)造。這樣就可以動(dòng)態(tài)加載帶有線程本地變量的模塊——變量首先需要在一個(gè)給定的線程中進(jìn)行構(gòu)造,之后其他線程就可以通過(guò)動(dòng)態(tài)加載模塊對(duì)線程本地變量進(jìn)行引用。

函數(shù)中聲明的線程本地變量,需要使用一個(gè)給定線程進(jìn)行初始化(通過(guò)第一波控制流將這些聲明傳遞給指定線程)。如果函數(shù)沒(méi)有被指定線程調(diào)用,那么這個(gè)函數(shù)中聲明的線程本地變量就不會(huì)構(gòu)造。本地靜態(tài)變量也是同樣的情況,除非其單獨(dú)的應(yīng)用于每一個(gè)線程。

靜態(tài)變量與線程本地變量會(huì)共享一些屬性——它們可以做進(jìn)一步的初始化(比如,動(dòng)態(tài)初始化);如果在構(gòu)造線程本地變量時(shí)拋出異常,srd::terminate()就會(huì)將程序終止。

析構(gòu)函數(shù)會(huì)在構(gòu)造線程本地變量的那個(gè)線程返回時(shí)調(diào)用,析構(gòu)順序是構(gòu)造的逆順序。當(dāng)初始化順序沒(méi)有指定時(shí),確定析構(gòu)函數(shù)和這些變量是否有相互依存關(guān)系就尤為重要了。當(dāng)線程本地變量的析構(gòu)函數(shù)拋出異常時(shí),std::terminate()會(huì)被調(diào)用,將程序終止。

當(dāng)線程調(diào)用std::exit()或從main()函數(shù)返回(等價(jià)于調(diào)用std::exit()作為main()的“返回值”)時(shí),線程本地變量也會(huì)為了這個(gè)線程進(jìn)行銷毀。應(yīng)用退出時(shí)還有線程在運(yùn)行,對(duì)于這些線程來(lái)說(shuō),線程本地變量的析構(gòu)函數(shù)就沒(méi)有被調(diào)用。

雖然,線程本地變量在不同線程上有不同的地址,不過(guò)還是可以獲取指向這些變量的一般指針。指針會(huì)在線程中,通過(guò)獲取地址的方式,引用相應(yīng)的對(duì)象。當(dāng)引用被銷毀的對(duì)象時(shí),會(huì)出現(xiàn)未定義行為,所以在向其他線程傳遞線程本地變量指針時(shí),就需要保證指向?qū)ο笏诘木€程結(jié)束后,不能對(duì)相應(yīng)的指針進(jìn)行解引用。