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

6.1 為并發(fā)設(shè)計的意義何在?

設(shè)計并發(fā)數(shù)據(jù)結(jié)構(gòu),意味著多個線程可以并發(fā)的訪問這個數(shù)據(jù)結(jié)構(gòu),線程可對這個數(shù)據(jù)結(jié)構(gòu)做相同或不同的操作,并且每一個線程都能在自己的自治域中看到該數(shù)據(jù)結(jié)構(gòu)。且在多線程環(huán)境下,無數(shù)據(jù)丟失和損毀,所有的數(shù)據(jù)需要維持原樣,且無條件競爭。這樣的數(shù)據(jù)結(jié)構(gòu),稱之為“線程安全”的數(shù)據(jù)結(jié)構(gòu)。通常情況下,當(dāng)多個線程對數(shù)據(jù)結(jié)構(gòu)進行同一并發(fā)操作是安全的,但不同操作則需要單線程獨立訪問數(shù)據(jù)結(jié)構(gòu)?;蛳喾?,當(dāng)線程執(zhí)行不同的操作時,對同一數(shù)據(jù)結(jié)構(gòu)的并發(fā)操作是安全的,而多線程執(zhí)行同樣的操作,則會出現(xiàn)問題。

實際的設(shè)計意義并不止上面提到的那樣:這就意味著,要為線程提供并發(fā)訪問數(shù)據(jù)結(jié)構(gòu)的機會。本質(zhì)上,是使用互斥量提供互斥特性:在互斥量的保護下,同一時間內(nèi)只有一個線程可以獲取互斥鎖?;コ饬繛榱吮Wo數(shù)據(jù),顯式的阻止了線程對數(shù)據(jù)結(jié)構(gòu)的并發(fā)訪問。

這被稱為序列化(serialzation):線程輪流訪問被保護的數(shù)據(jù)。這其實是對數(shù)據(jù)進行串行的訪問,而非并發(fā)。因此,你需要對數(shù)據(jù)結(jié)構(gòu)的設(shè)計進行仔細斟酌,確保其能真正并發(fā)訪問。雖然,一些數(shù)據(jù)結(jié)構(gòu)有著比其他數(shù)據(jù)結(jié)構(gòu)多的并發(fā)訪問范圍,但是在所有情況下的思路都是一樣的:減少保護區(qū)域,減少序列化操作,就能提升并發(fā)訪問的潛力。

在我們進行數(shù)據(jù)結(jié)構(gòu)的設(shè)計之前,讓我們快速的瀏覽一下,在并發(fā)設(shè)計中的指導(dǎo)建議。

6.1.1 數(shù)據(jù)結(jié)構(gòu)并發(fā)設(shè)計的指導(dǎo)與建議(指南)

如之前提到的,當(dāng)設(shè)計并發(fā)數(shù)據(jù)結(jié)構(gòu)時,有兩方面需要考量:一是確保訪問是安全的,二是能真正的并發(fā)訪問。在第3章的時候,已經(jīng)對如何保證數(shù)據(jù)結(jié)構(gòu)是線程安全的做過簡單的描述:

  • 確保無線程能夠看到,數(shù)據(jù)結(jié)構(gòu)的“不變量”破壞時的狀態(tài)。

  • 小心那些會引起條件競爭的接口,提供完整操作的函數(shù),而非操作步驟。

  • 注意數(shù)據(jù)結(jié)構(gòu)的行為是否會產(chǎn)生異常,從而確?!安蛔兞俊钡臓顟B(tài)穩(wěn)定。

  • 將死鎖的概率降到最低。使用數(shù)據(jù)結(jié)構(gòu)時,需要限制鎖的范圍,且避免嵌套鎖的存在。

在你思考設(shè)計細節(jié)前,你還需要考慮這個數(shù)據(jù)結(jié)構(gòu)對于使用者來說有什么限制;當(dāng)一個線程通過一個特殊的函數(shù)對數(shù)據(jù)結(jié)構(gòu)進行訪問時,那么還有哪些函數(shù)能被其他的線程安全調(diào)用呢?

這是一個很重要的問題,普通的構(gòu)造函數(shù)和析構(gòu)函數(shù)需要獨立訪問數(shù)據(jù)結(jié)構(gòu),所以用戶在使用的時候,就不能在構(gòu)造函數(shù)完成前,或析構(gòu)函數(shù)完成后對數(shù)據(jù)結(jié)構(gòu)進行訪問。當(dāng)數(shù)據(jù)結(jié)構(gòu)支持賦值操作,swap(),或拷貝構(gòu)造時,作為數(shù)據(jù)結(jié)構(gòu)的設(shè)計者,即使數(shù)據(jù)結(jié)構(gòu)中有大量的函數(shù)被線程所操縱時,你也需要保證這些操作在并發(fā)環(huán)境下是安全的(或確保這些操作能夠獨立訪問),以保證并發(fā)訪問時不會出現(xiàn)錯誤。

第二個方面是,確保真正的并發(fā)訪問。這里沒法提供更多的指導(dǎo)意見;不過,作為一個數(shù)據(jù)結(jié)構(gòu)的設(shè)計者,在設(shè)計數(shù)據(jù)結(jié)構(gòu)時,自行考慮以下問題:

  • 鎖的范圍中的操作,是否允許在鎖外執(zhí)行?

  • 數(shù)據(jù)結(jié)構(gòu)中不同的區(qū)域是否能被不同的互斥量所保護?

  • 所有操作都需要同級互斥量保護嗎?

  • 能否對數(shù)據(jù)結(jié)構(gòu)進行簡單的修改,以增加并發(fā)訪問的概率,且不影響操作語義?

這些問題都源于一個指導(dǎo)思想:如何讓序列化訪問最小化,讓真實并發(fā)最大化?允許線程并發(fā)讀取的數(shù)據(jù)結(jié)構(gòu)并不少見,而對數(shù)據(jù)結(jié)構(gòu)的修改,必須是單線程獨立訪問。這種結(jié)構(gòu),類似于boost::shared_mutex。同樣的,這種數(shù)據(jù)結(jié)構(gòu)也很常見——支持在多線程執(zhí)行不同的操作時,并序列化執(zhí)行相同的操作的線程(你很快就能看到)。

最簡單的線程安全結(jié)構(gòu),通常使用的是互斥量和鎖,對數(shù)據(jù)進行保護。雖然,這么做還是有問題(如同在第3中提到的那樣),不過這樣相對簡單,且保證只有一個線程在同一時間對數(shù)據(jù)結(jié)構(gòu)進行一次訪問。為了讓你輕松的設(shè)計線程安全的數(shù)據(jù)結(jié)構(gòu),接下來了解一下基于鎖的數(shù)據(jù)結(jié)構(gòu),以及第7章將提到的無鎖并發(fā)數(shù)據(jù)結(jié)構(gòu)的設(shè)計。