在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ C/ 7.3 對于設計無鎖數(shù)據(jù)結(jié)構(gòu)的指導建議
3.4 本章總結(jié)
6.3 基于鎖設計更加復雜的數(shù)據(jù)結(jié)構(gòu)
6.1 為并發(fā)設計的意義何在?
5.2 <code>C++</code>中的原子操作和原子類型
A.7 自動推導變量類型
2.1 線程管理的基礎
8.5 在實踐中設計并發(fā)代碼
2.4 運行時決定線程數(shù)量
2.2 向線程函數(shù)傳遞參數(shù)
第4章 同步并發(fā)操作
2.3 轉(zhuǎn)移線程所有權(quán)
8.3 為多線程性能設計數(shù)據(jù)結(jié)構(gòu)
6.4 本章總結(jié)
7.3 對于設計無鎖數(shù)據(jù)結(jié)構(gòu)的指導建議
關于這本書
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)存模型基礎
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ā)代碼設計
3.3 保護共享數(shù)據(jù)的替代設施
附錄D C++線程庫參考
第7章 無鎖并發(fā)數(shù)據(jù)結(jié)構(gòu)設計
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)設計
封面圖片介紹
7.2 無鎖數(shù)據(jù)結(jié)構(gòu)的例子
8.6 本章總結(jié)
8.1 線程間劃分工作的技術(shù)
4.2 使用期望等待一次性事件
8.4 設計并發(fā)代碼的注意事項
D.5 &lt;mutex&gt;頭文件
3.1 共享數(shù)據(jù)帶來的問題
資源
9.3 本章總結(jié)
10.3 本章總結(jié)
10.1 與并發(fā)相關的錯誤類型
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ù)

7.3 對于設計無鎖數(shù)據(jù)結(jié)構(gòu)的指導建議

本章中的例子中,看到了一些復雜的代碼可讓無鎖結(jié)構(gòu)工作正常。如果要設計自己的數(shù)據(jù)結(jié)構(gòu),一些指導建議可以幫助你找到設計重點。第6章中關于并發(fā)通用指導建議還適用,不過這里需要更多的建議。我從例子中抽取了幾個實用的指導建議,在你設計無鎖結(jié)構(gòu)數(shù)據(jù)的時候就可以直接引用。

7.3.1 指導建議:使用std::memory_order_seq_cst的原型

std::memory_order_seq_cst比起其他內(nèi)存序要簡單的多,因為所有操作都將其作為總序。本章的所有例子,都是從std::memory_order_seq_cst開始,只有當基本操作正常工作的時候,才放寬內(nèi)存序的選擇。在這種情況下,使用其他內(nèi)存序就是進行優(yōu)化(早起可以不用這樣做)。通常,當你看整套代碼對數(shù)據(jù)結(jié)構(gòu)的操作后,才能決定是否要放寬該操作的內(nèi)存序選擇。所以,嘗試放寬選擇,可能會讓你輕松一些。在測試后的時候,工作的代碼可能會很復雜(不過,不能完全保證內(nèi)存序正確)。除非你有一個算法檢查器,可以系統(tǒng)的測試,線程能看到的所有可能性組合,這樣就能保證指定內(nèi)存序的正確性(這樣的測試的確存在),僅是執(zhí)行實現(xiàn)代碼是遠遠不夠的。

7.3.2 指導建議:對無鎖內(nèi)存的回收策略

這里與無鎖代碼最大的區(qū)別就是內(nèi)存管理。當有其他線程對節(jié)點進行訪問的時候,節(jié)點無法被任一線程刪除;為避免過多的內(nèi)存使用,還是希望這個節(jié)點在能刪除的時候盡快刪除。本章中介紹了三種技術(shù)來保證內(nèi)存可以被安全的回收:

  • 等待無線程對數(shù)據(jù)結(jié)構(gòu)進行訪問時,刪除所有等待刪除的對象。

  • 使用風險指針來標識正在被線程訪問的對象。

  • 對對象進行引用計數(shù),當沒有線程對對象進行引用時,將其刪除。

在所有例子中,主要的想法都是使用一種方式去跟蹤指定對象上的線程訪問數(shù)量,當沒有現(xiàn)成對對象進行引用的時候,將對象刪除。當然,在無鎖數(shù)據(jù)結(jié)構(gòu)中,還有很多方式可以用來回收內(nèi)存。例如,理想情況下使用一個垃圾收集器。比起算法來說,其實現(xiàn)更容易一些。只需要讓回收器知道,當節(jié)點沒被引用的時候,回收節(jié)點,就可以了。

其他替代方案就是循環(huán)使用節(jié)點,只在數(shù)據(jù)結(jié)構(gòu)被銷毀的時候才將節(jié)點完全刪除。因為節(jié)點能被復用,那么就不會有非法的內(nèi)存,所以這就能避免未定義行為的發(fā)生。這種方式的缺點:產(chǎn)生“ABA問題”。

7.3.3 指導建議:小心ABA問題

在“基于比較/交換”的算法中要格外小心“ABA問題”。其流程是:

  1. 線程1讀取原子變量x,并且發(fā)現(xiàn)其值是A。
  2. 線程1對這個值進行一些操作,比如,解引用(當其是一個指針的時候),或做查詢,或其他操作。
  3. 操作系統(tǒng)將線程1掛起。
  4. 其他線程對x執(zhí)行一些操作,并且將其值改為B。
  5. 另一個線程對A相關的數(shù)據(jù)進行修改(線程1持有),讓其不再合法??赡軙卺尫胖羔樦赶虻膬?nèi)存時,代碼產(chǎn)生劇烈的反應(大問題);或者只是修改了相關值而已(小問題)。
  6. 再來一個線程將x的值改回為A。如果A是一個指針,那么其可能指向一個新的對象,只是與舊對象共享同一個地址而已。
  7. 線程1繼續(xù)運行,并且對x執(zhí)行“比較/交換”操作,將A進行對比。這里,“比較/交換”成功(因為其值還是A),不過這是一個錯誤的A(the wrong A value)。從第2步中讀取的數(shù)據(jù)不再合法,但是線程1無法言明這個問題,并且之后的操作將會損壞數(shù)據(jù)結(jié)構(gòu)。

本章提到的算法不存在這個問題,不過在無鎖的算法中,這個問題很常見。解決這個問題的一般方法是,讓變量x中包含一個ABA計數(shù)器?!氨容^/交換”會對加入計數(shù)器的x進行操作。每次的值都不一樣,計數(shù)隨之增長,所以在x還是原值的前提下,即使有線程對x進行修改,“比較/交換”還是會失敗。

“ABA問題”在使用釋放鏈表和循環(huán)使用節(jié)點的算法中很是普遍,而將節(jié)點返回給分配器,則不會引起這個問題。

7.3.4 指導建議:識別忙等待循環(huán)和幫助其他線程

在最終隊列的例子中,已經(jīng)見識到線程在執(zhí)行push操作時,必須等待另一個push操作流程的完成。等待線程就會被孤立,將會陷入到忙等待循環(huán)中,當線程嘗試失敗的時候,會繼續(xù)循環(huán),這樣就會浪費CPU的計算周期。當忙等待循環(huán)結(jié)束時,就像一個阻塞操作解除,和使用互斥鎖的行為一樣。通過對算法的修改,當之前的線程還沒有完成操作前,讓等待線程執(zhí)行未完成的步驟,就能讓忙等待的線程不再被阻塞。在隊列例中,需要將一個數(shù)據(jù)成員轉(zhuǎn)換為一個原子變量,而不是使用非原子變量和使用“比較/交換”操作來做這件事;要是在更加復雜的數(shù)據(jù)結(jié)構(gòu)中,這將需要更加多的變化來滿足需求。