C++ 並發編程實戰, 2/e C++ Concurrency in Action, 2/e

[英]安東尼·威廉姆斯(Anthony Williams)

  • C++ 並發編程實戰, 2/e-preview-1
  • C++ 並發編程實戰, 2/e-preview-2
C++ 並發編程實戰, 2/e-preview-1

買這商品的人也買了...

商品描述

這是一本介紹C++並發和多線程編程的深度指南。本書從C++標準程序庫的各種工具講起,介紹線程管控、在線程間共享數據、並發操作的同步、C++內存模型和原子操作等內容。同時,本書還介紹基於鎖的並發數據結構、無鎖數據結構、並發代碼,以及高級線程管理、並行算法函數、多線程應用的測試和除錯。本書還通過附錄及線上資源提供豐富的補充資料,以幫助讀者更完整、細致地掌握C++並發編程的知識脈絡。

本書適合需要深入瞭解C++多線程開發的讀者,以及使用C++進行各類軟件開發的開發人員、測試人員,還可以作為C++線程庫的參考工具書。

作者簡介

安東尼·威廉姆斯(Anthony Williams),C++開發人員、顧問、培訓師,英國標準協會C++標準組成員,擁有超過20年的C++開發經驗,獨立編寫或合著了眾多C++標準委員會文件,為C++11標準引入了線程庫,實現了工具“just::thread Pro”(Just Software Solutions公司的產品),並持續致力於開發C++的新特性,以增強C++並發工具集的功能,這兩者都遵循C++標準和提案。

目錄大綱

第 1章 你好,C++並發世界 1
1.1 什麼是並發 2
1.1.1 計算機系統中的並發 2
1.1.2 並發的方式 4
1.1.3 並發與並行 5
1.2 為什麼使用並發技術 6
1.2.1 為分離關注點而並發 6
1.2.2 為性能而並發:任務並行和數據並行 7
1.2.3 什麼時候避免並發 8
1.3 並發與C++多線程 9
1.3.1 C++多線程簡史 9
1.3.2 新標準對並發的支持 10
1.3.3 C++14和C++17進一步支持並發和並行 10
1.3.4 標準C++線程庫的效率 10
1.3.5 平台專屬的工具 12
1.4 啟程上路 12
實例—“Hello Concurrent World” 12
1.5 小結 13
第 2章 線程管控 15
2.1 線程的基本管控 15
2.1.1 發起線程 16
2.1.2 等待線程完成 19
2.1.3 在出現異常的情況下等待 19
2.1.4 在後台運行線程 21
2.2 向線程函數傳遞參數 23
2.3 移交線程歸屬權 26
2.4 在運行時選擇線程數量 30
2.5 識別線程 33
2.6 小結 35
第3章 在線程間共享數據 37
3.1 線程間共享數據的問題 38
3.1.1 條件競爭 39
3.1.2 防止惡性條件競爭 40
3.2 用互斥保護共享數據 41
3.2.1 在C++中使用互斥 41
3.2.2 組織和編排代碼以保護共享數據 43
3.2.3 發現接口固有的條件競爭 44
3.2.4 死鎖:問題和解決方法 51
3.2.5 防範死鎖的補充準則 53
3.2.6 運用std::unique_lock<>靈活加鎖 60
3.2.7 在不同作用域之間轉移互斥歸屬權 61
3.2.8 按適合的粒度加鎖 62
3.3 保護共享數據的其他工具 64
3.3.1 在初始化過程中保護共享數據 65
3.3.2 保護甚少更新的數據結構 68
3.3.3 遞歸加鎖 70
3.4 小結 71
第4章 並發操作的同步 73
4.1 等待事件或等待其他條件 73
4.1.1 憑藉條件變量等待條件成立 75
4.1.2 利用條件變量構建線程安全的隊列 77
4.2 使用future等待一次性事件發生 82
4.2.1 從後台任務返回值 83
4.2.2 關聯future實例和任務 85
4.2.3 創建std::promise 88
4.2.4 將異常保存到future中 90
4.2.5 多個線程一起等待 91
4.3 限時等待 94
4.3.1 時鐘類 94
4.3.2 時長類 95
4.3.3 時間點類 97
4.3.4 接受超時時限的函數 99
4.4 運用同步操作簡化代碼 101
4.4.1 利用future進行函數式編程 101
4.4.2 使用消息傳遞進行同步 106
4.4.3 符合併發技術規約的後續風格並發 110
4.4.4 後續函數的連鎖調用 112
4.4.5 等待多個future 115
4.4.6 運用std::experimental::when_any()函數等待多個
future,直到其中之一準備就緒 117
4.4.7 線程閂和線程卡——並發技術規約提出的新特性 120
4.4.8 基本的線程閂類std::experimental::latch 121
4.4.9 基本的線程卡類std::experimental::barrier 122
4.4.10 std::experimental::flex_barrier——std::experimental::barrier的靈活版本 124
4.5 小結 125
第5章 C++內存模型和原子操作 127
5.1 內存模型基礎 128
5.1.1 對象和內存區域 128
5.1.2 對象、內存區域和並發 129
5.1.3 改動序列 130
5.2 C++中的原子操作及其類別 131
5.2.1 標準原子類型 131
5.2.2 操作std::atomic_flag 135
5.2.3 操作std::atomic 137
5.2.4 操作std::atomic:算術形式的指針運算 139
5.2.5 操作標準整數原子類型 140
5.2.6 泛化的std::atomic<>類模板 141
5.2.7 原子操作的非成員函數 143
5.3 同步操作和強制次序 145
5.3.1 同步關係 147
5.3.2 先行關係 147
5.3.3 原子操作的內存次序 149
5.3.4 釋放序列和同步關係 167
5.3.5 柵欄 169
5.3.6 憑藉原子操作令非原子操作服從內存次序 171
5.3.7 強制非原子操作服從內存次序 172
5.4 小結 175
第6章 設計基於鎖的並發數據結構 177
6.1 並發設計的內涵 178
6.2 基於鎖的並發數據結構 179
6.2.1 採用鎖實現線程安全的棧容器 180
6.2.2 採用鎖和條件變量實現線程安全的隊列容器 182
6.2.3 採用精細粒度的鎖和條件變量實現線程安全的隊列容器 186
6.3 設計更複雜的基於鎖的並發數據結構 198
6.3.1 採用鎖編寫線程安全的查找表 198
6.3.2 採用多種鎖編寫線程安全的鍊錶 204
6.4 小結 208
第7章 設計無鎖數據結構 209
7.1 定義和推論 210
7.1.1 非阻塞型數據結構 210
7.1.2 無鎖數據結構 211
7.1.3 無須等待的數據結構 212
7.1.4 無鎖數據結構的優點和缺點 212
7.2 無鎖數據結構範例 213
7.2.1 實現線程安全的無鎖棧 214
7.2.2 制止麻煩的內存洩漏:在無鎖數據結構中管理內存 217
7.2.3 運用風險指針檢測無法回收的節點 223
7.2.4 借引用計數檢測正在使用中的節點 231
7.2.5 為無鎖棧容器施加內存模型 237
7.2.6 實現線程安全的無鎖隊列 242
7.3 實現無鎖數據結構的原則 254
7.3.1 原則1:在原型設計中使用std::memory_order_seq_cst次序 254
7.3.2 原則2:使用無鎖的內存回收方案 255
7.3.3 原則3:防範ABA問題 255
7.3.4 原則4:找出忙等循環,協助其他線程 256
7.4 小結 256
第8章 設計並發代碼 257
8.1 在線程間切分任務的方法 258
8.1.1 先在線程間切分數據,再開始處理 258
8.1.2 以遞歸方式劃分數據 259
8.1.3 依據工作類別劃分任務 263
8.2 影響並發代碼性能的因素 266
8.2.1 處理器的數量 266
8.2.2 數據競爭和緩存乒乓(cache ping-pong) 267
8.2.3 不經意共享 270
8.2.4 數據的緊湊程度 270
8.2.5 過度任務切換與線程過飽和 271
8.3 設計數據結構以提升多線程程序的性能 272
8.3.1 針對複雜操作的數據劃分 272
8.3.2 其他數據結構的訪問模式 275
8.4 設計並發代碼時要額外考慮的因素 276
8.4.1 並行算法代碼中的異常安全 276
8.4.2 可伸縮性和Amdahl定律 283
8.4.3 利用多線程“掩藏”等待行為 285
8.4.4 借並發特性改進響應能力 286
8.5 並發代碼的設計實踐 287
8.5.1 std::for_each()的並行實現 288
8.5.2 std::find()的並行實現 290
8.5.3 std::partial_sum()的並行實現 295
8.6 小結 305
第9章 高級線程管理 307
9.1 線程池 308
9.1.1 最簡易可行的線程池 308
9.1.2 等待提交給線程池的任務完成運行 310
9.1.3 等待其他任務完成的任務 313
9.1.4 避免任務隊列上的爭奪 316
9.1.5 任務竊取 318
9.2 中斷線程 322
9.2.1 發起一個線程,以及把它中斷 323
9.2.2 檢測線程是否被中斷 324
9.2.3 中斷條件變量上的等待 325
9.2.4 中斷條件變量std::condition_variable_any上的等待 328
9.2.5 中斷其他阻塞型等待 330
9.2.6 處理中斷 331
9.2.7 在應用程序退出時中斷後台任務 332
9.3 小結 333
第 10章 並行算法函數 335
10.1 並行化的標準庫算法函數 335
10.2 執行策略 336
10.2.1 因指定執行策略而普遍產生的作用 336
10.2.2 std::execution::sequenced_policy 337
10.2.3 std::execution::parallel_policy 338
10.2.4 std::execution::parallel_unsequenced_policy 339
10.3 C++標準庫的並行算法函數 339
10.3.1 並行算法函數的使用範例 342
10.3.2 訪問計數 344
10.4 小結 346
第 11章 多線程應用的測試和除錯 347
11.1 與並發相關的錯誤類型 347
11.1.1 多餘的阻塞 348
11.1.2 條件競爭 348
11.2 定位並發相關的錯誤的技法 349
11.2.1 審查代碼並定位潛在錯誤 350
11.2.2 通過測試定位與並發相關的錯誤 352
11.2.3 設計可測試的代碼 353
11.2.4 多線程測試技術 355
11.2.5 以特定結構組織多線程的測試代碼 357
11.2.6 測試多線程代碼的性能 360
11.3 小結360

附錄A C++11精要:部分語言特性 361
A. 1 右值引用 361
A. 1.1 移動語義 362
A. 1.2 右值引用和函數模板 365
A. 2 刪除函數 366
A. 3 默認函數 368
A. 4 常量表達式函數 371
A. 4.1 constexpr關鍵字和用戶定義型別 373
A. 4.2 constexpr對象 376
A. 4.3 constexpr函數要符合的條件 376
A. 4.4 constexpr與模板 377
A. 5 lambda函數 377
A. 6 變參模板 382
A. 7 自動推導變量的型別 386
A. 8 線程局部變量 387
A. 9 類模板的參數推導 389
A. 10 小結 389
附錄B 各並發程序庫的簡要對比 391
附錄C 消息傳遞程序庫和完整的自動櫃員機範例 393