這是一本介紹C 并發(fā)和多線程編程的深度指南。本書從C 標(biāo)準(zhǔn)程序庫的各種工具講起,介紹線程管控、在線程間共享數(shù)據(jù)、并發(fā)操作的同步、C 內(nèi)存模型和原子操作等內(nèi)容。同時,本書還介紹基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu)、無鎖數(shù)據(jù)結(jié)構(gòu)、并發(fā)代碼,以及高級線程管理、并行算法函數(shù)、多線程應(yīng)用的測試和除錯。本書還通過附錄及線上資源提供豐富的補充資料,以幫助讀者更完整、細(xì)致地掌握C 并發(fā)編程的知識脈絡(luò)。
本書適合需要深入了解C 多線程開發(fā)的讀者,以及使用C 進行各類軟件開發(fā)的開發(fā)人員、測試人員,還可以作為C 線程庫的參考工具書。
1.這是一本介紹C 并發(fā)和多線編程的深度指南,囊括了C 并發(fā)編程的多個方面,涉及啟動新線程以及設(shè)計全功能的多線程算法和數(shù)據(jù)結(jié)構(gòu)等核心知識點;
2.本書譯文經(jīng)過反復(fù)推敲,作譯者協(xié)同參與全書內(nèi)容的翻譯和審讀,代碼配有詳細(xì)的中文注釋,內(nèi)容簡潔易懂;
3.譯者還基于自己的開發(fā)經(jīng)驗,補充了許多延伸知識點,適合想要深入了解C 多線程的開發(fā)人員深入學(xué)習(xí);
4.本書提供強大的配套資源,包括近200頁的電子版附錄D以及140多份配套代碼文件。
安東尼·威廉姆斯(Anthony Williams),C 開發(fā)人員、顧問、培訓(xùn)師,英國標(biāo)準(zhǔn)協(xié)會C 標(biāo)準(zhǔn)組成員,擁有超過20年的C 開發(fā)經(jīng)驗,獨立編寫或合著了眾多C 標(biāo)準(zhǔn)委員會文件,為C 11標(biāo)準(zhǔn)引入了線程庫,實現(xiàn)了工具just::thread Pro(Just Software Solutions公司的產(chǎn)品),并持續(xù)致力于開發(fā)C 的新特性,以增強C 并發(fā)工具集的功能,這兩者都遵循C 標(biāo)準(zhǔn)和提案。
第 1章 你好,C 并發(fā)世界 1
1.1 什么是并發(fā) 2
1.1.1 計算機系統(tǒng)中的并發(fā) 2
1.1.2 并發(fā)的方式 4
1.1.3 并發(fā)與并行 5
1.2 為什么使用并發(fā)技術(shù) 6
1.2.1 為分離關(guān)注點而并發(fā) 6
1.2.2 為性能而并發(fā):任務(wù)并行和數(shù)據(jù)并行 7
1.2.3 什么時候避免并發(fā) 8
1.3 并發(fā)與C 多線程 9
1.3.1 C 多線程簡史 9
1.3.2 新標(biāo)準(zhǔn)對并發(fā)的支持 10
1.3.3 C 14和C 17進一步
支持并發(fā)和并行 10
1.3.4 標(biāo)準(zhǔn)C 線程庫的效率 10
1.3.5 平臺專屬的工具 12
1.4 啟程上路 12
實例Hello Concurrent World 12
1.5 小結(jié) 13
第 2章 線程管控 15
2.1 線程的基本管控 15
2.1.1 發(fā)起線程 16
2.1.2 等待線程完成 19
2.1.3 在出現(xiàn)異常的情況下等待 19
2.1.4 在后臺運行線程 21
2.2 向線程函數(shù)傳遞參數(shù) 23
2.3 移交線程歸屬權(quán) 26
2.4 在運行時選擇線程數(shù)量 30
2.5 識別線程 33
2.6 小結(jié) 35
第3章 在線程間共享數(shù)據(jù) 37
3.1 線程間共享數(shù)據(jù)的問題 38
3.1.1 條件競爭 39
3.1.2 防止惡性條件競爭 40
3.2 用互斥保護共享數(shù)據(jù) 41
3.2.1 在C 中使用互斥 41
3.2.2 組織和編排代碼以保護共享數(shù)據(jù) 43
3.2.3 發(fā)現(xiàn)接口固有的條件競爭 44
3.2.4 死鎖:問題和解決方法 51
3.2.5 防范死鎖的補充準(zhǔn)則 53
3.2.6 運用std::unique_lock<>靈活加鎖 60
3.2.7 在不同作用域之間轉(zhuǎn)移互斥歸屬權(quán) 61
3.2.8 按適合的粒度加鎖 62
3.3 保護共享數(shù)據(jù)的其他工具 64
3.3.1 在初始化過程中保護共享數(shù)據(jù) 65
3.3.2 保護甚少更新的數(shù)據(jù)結(jié)構(gòu) 68
3.3.3 遞歸加鎖 70
3.4 小結(jié) 71
第4章 并發(fā)操作的同步 73
4.1 等待事件或等待其他條件 73
4.1.1 憑借條件變量等待條件成立 75
4.1.2 利用條件變量構(gòu)建線程安全的隊列 77
4.2 使用future等待一次性事件發(fā)生 82
4.2.1 從后臺任務(wù)返回值 83
4.2.2 關(guān)聯(lián)future實例和任務(wù) 85
4.2.3 創(chuàng)建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 接受超時時限的函數(shù) 99
4.4 運用同步操作簡化代碼 101
4.4.1 利用future進行函數(shù)式編程 101
4.4.2 使用消息傳遞進行同步 106
4.4.3 符合并發(fā)技術(shù)規(guī)約的后續(xù)風(fēng)格并發(fā) 110
4.4.4 后續(xù)函數(shù)的連鎖調(diào)用 112
4.4.5 等待多個future 115
4.4.6 運用std::experimental::when_any()函數(shù)等待多個
future,直到其中之一準(zhǔn)備就緒 117
4.4.7 線程閂和線程卡并發(fā)技術(shù)規(guī)約提出的新特性 120
4.4.8 基本的線程閂類std::experimental::latch 121
4.4.9 基本的線程卡類std::experimental::barrier 122
4.4.10 std::experimental::flex_barrierstd::experimental::barrier的靈活版本 124
4.5 小結(jié) 125
第5章 C 內(nèi)存模型和原子操作 127
5.1 內(nèi)存模型基礎(chǔ) 128
5.1.1 對象和內(nèi)存區(qū)域 128
5.1.2 對象、內(nèi)存區(qū)域和并發(fā) 129
5.1.3 改動序列 130
5.2 C 中的原子操作及其類別 131
5.2.1 標(biāo)準(zhǔn)原子類型 131
5.2.2 操作std::atomic_flag 135
5.2.3 操作std::atomic 137
5.2.4 操作std::atomic:算術(shù)形式的指針運算 139
5.2.5 操作標(biāo)準(zhǔn)整數(shù)原子類型 140
5.2.6 泛化的std::atomic<>類模板 141
5.2.7 原子操作的非成員函數(shù) 143
5.3 同步操作和強制次序 145
5.3.1 同步關(guān)系 147
5.3.2 先行關(guān)系 147
5.3.3 原子操作的內(nèi)存次序 149
5.3.4 釋放序列和同步關(guān)系 167
5.3.5 柵欄 169
5.3.6 憑借原子操作令非原子操作服從內(nèi)存次序 171
5.3.7 強制非原子操作服從內(nèi)存次序 172
5.4 小結(jié) 175
第6章 設(shè)計基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu) 177
6.1 并發(fā)設(shè)計的內(nèi)涵 178
6.2 基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu) 179
6.2.1 采用鎖實現(xiàn)線程安全的棧容器 180
6.2.2 采用鎖和條件變量實現(xiàn)線程安全的隊列容器 182
6.2.3 采用精細(xì)粒度的鎖和條件變量實現(xiàn)線程安全的隊列容器 186
6.3 設(shè)計更復(fù)雜的基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu) 198
6.3.1 采用鎖編寫線程安全的查找表 198
6.3.2 采用多種鎖編寫線程安全的鏈表 204
6.4 小結(jié) 208
第7章 設(shè)計無鎖數(shù)據(jù)結(jié)構(gòu) 209
7.1 定義和推論 210
7.1.1 非阻塞型數(shù)據(jù)結(jié)構(gòu) 210
7.1.2 無鎖數(shù)據(jù)結(jié)構(gòu) 211
7.1.3 無須等待的數(shù)據(jù)結(jié)構(gòu) 212
7.1.4 無鎖數(shù)據(jù)結(jié)構(gòu)的優(yōu)點和缺點 212
7.2 無鎖數(shù)據(jù)結(jié)構(gòu)范例 213
7.2.1 實現(xiàn)線程安全的無鎖!214
7.2.2 制止麻煩的內(nèi)存泄漏:在無鎖數(shù)據(jù)結(jié)構(gòu)中管理內(nèi)存 217
7.2.3 運用風(fēng)險指針檢測無法回收的節(jié)點 223
7.2.4 借引用計數(shù)檢測正在使用中的節(jié)點 231
7.2.5 為無鎖棧容器施加內(nèi)存模型 237
7.2.6 實現(xiàn)線程安全的無鎖隊列 242
7.3 實現(xiàn)無鎖數(shù)據(jù)結(jié)構(gòu)的原則 254
7.3.1 原則1:在原型設(shè)計中使用std::memory_order_seq_cst次序 254
7.3.2 原則2:使用無鎖的內(nèi)存回收方案 255
7.3.3 原則3:防范ABA問題 255
7.3.4 原則4:找出忙等循環(huán),協(xié)助其他線程 256
7.4 小結(jié) 256
第8章 設(shè)計并發(fā)代碼 257
8.1 在線程間切分任務(wù)的方法 258
8.1.1 先在線程間切分?jǐn)?shù)據(jù),再開始處理 258
8.1.2 以遞歸方式劃分?jǐn)?shù)據(jù) 259
8.1.3 依據(jù)工作類別劃分任務(wù) 263
8.2 影響并發(fā)代碼性能的因素 266
8.2.1 處理器的數(shù)量 266
8.2.2 數(shù)據(jù)競爭和緩存乒乓(cache ping-pong) 267
8.2.3 不經(jīng)意共享 270
8.2.4 數(shù)據(jù)的緊湊程度 270
8.2.5 過度任務(wù)切換與線程過飽和 271
8.3 設(shè)計數(shù)據(jù)結(jié)構(gòu)以提升多線程程序的性能 272
8.3.1 針對復(fù)雜操作的數(shù)據(jù)劃分 272
8.3.2 其他數(shù)據(jù)結(jié)構(gòu)的訪問模式 275
8.4 設(shè)計并發(fā)代碼時要額外考慮的因素 276
8.4.1 并行算法代碼中的異常安全 276
8.4.2 可伸縮性和Amdahl定律 283
8.4.3 利用多線程掩藏等待行為 285
8.4.4 借并發(fā)特性改進響應(yīng)能力 286
8.5 并發(fā)代碼的設(shè)計實踐 287
8.5.1 std::for_each()的并行實現(xiàn) 288
8.5.2 std::find()的并行實現(xiàn) 290
8.5.3 std::partial_sum()的并行實現(xiàn) 295
8.6 小結(jié) 305
第9章 高級線程管理 307
9.1 線程池 308
9.1.1 簡易可行的線程池 308
9.1.2 等待提交給線程池的任務(wù)完成運行 310
9.1.3 等待其他任務(wù)完成的任務(wù) 313
9.1.4 避免任務(wù)隊列上的爭奪 316
9.1.5 任務(wù)竊取 318
9.2 中斷線程 322
9.2.1 發(fā)起一個線程,以及把它中斷 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 在應(yīng)用程序退出時中斷后臺任務(wù) 332
9.3 小結(jié) 333
第 10章 并行算法函數(shù) 335
10.1 并行化的標(biāo)準(zhǔn)庫算法函數(shù) 335
10.2 執(zhí)行策略 336
10.2.1 因指定執(zhí)行策略而普遍產(chǎn)生的作用 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 標(biāo)準(zhǔn)庫的并行算法函數(shù) 339
10.3.1 并行算法函數(shù)的使用范例 342
10.3.2 訪問計數(shù) 344
10.4 小結(jié) 346
第 11章 多線程應(yīng)用的測試和除錯 347
11.1 與并發(fā)相關(guān)的錯誤類型 347
11.1.1 多余的阻塞 348
11.1.2 條件競爭 348
11.2 定位并發(fā)相關(guān)的錯誤的技法 349
11.2.1 審查代碼并定位潛在錯誤 350
11.2.2 通過測試定位與并發(fā)相關(guān)的錯誤 352
11.2.3 設(shè)計可測試的代碼 353
11.2.4 多線程測試技術(shù) 355
11.2.5 以特定結(jié)構(gòu)組織多線程的測試代碼 357
11.2.6 測試多線程代碼的性能 360
11.3 小結(jié)360
附錄A C 11精要:部分語言特性 361
A.1 右值引用 361
A.1.1 移動語義 362
A.1.2 右值引用和函數(shù)模板 365
A.2 刪除函數(shù) 366
A.3 默認(rèn)函數(shù) 368
A.4 常量表達式函數(shù) 371
A.4.1 constexpr關(guān)鍵字和用戶定義型別 373
A.4.2 constexpr對象 376
A.4.3 constexpr函數(shù)要符合的條件 376
A.4.4 constexpr與模板 377
A.5 lambda函數(shù) 377
A.6 變參模板 382
A.7 自動推導(dǎo)變量的型別 386
A.8 線程局部變量 387
A.9 類模板的參數(shù)推導(dǎo) 389
A.10 小結(jié) 389
附錄B 各并發(fā)程序庫的簡要
對比 391
附錄C 消息傳遞程序庫和完整
的自動柜員機范例 393