第一部分 概念 1
第1章 概述 1
1.1 为什么需要并发 1
1.2 程序架构与并发 2
1.3 并行的层次 4
1.4 为什么不需要并发 5
1.5 小结 5
延伸阅读 6
第2章 同步与时间 7
2.1 程序状态的管理 7
2.1.1 共享状态与私有状态的区分 8
2.1.2 状态机与时间 11
2.1.3 独立性 17
2.1.4 不变性 19
2.2 同步:种类与实现技术 22
2.2.1 数据同步 23
2.2.2 协作与控制同步 35
2.3 小结 43
延伸阅读 43
第二部分 机制 45
第3章 线程 45
3.1 从高层面上来看线程 45
3.1.1 Windows线程是什么 46
3.1.2 CLR线程是什么 48
3.1.3 显式线程操作及其替代方法 49
3.2 线程的诞生与消亡 50
3.2.1 线程的创建 50
3.2.2 线程终止 59
3.2.3 DllMain 66
3.2.4 线程局部存储 68
3.3 小结 72
延伸阅读 73
第4章 线程的高级内容 74
4.1 线程的状态 74
4.1.1 用户态线程栈 74
4.1.2 内部数据结构(KTHREAD、ETHREAD和TEB) 85
4.1.3 上下文 89
4.2 线程的创建过程与终止过程 90
4.2.1 线程创建的具体流程 90
4.2.2 线程终止的具体流程 91
4.3 线程调度 91
4.3.1 线程的状态 92
4.3.2 优先级 94
4.3.3 时间片 96
4.3.4 优先级与时间片调整 97
4.3.5 睡眠与退让 99
4.3.6 挂起 100
4.3.7 关联性:优先在某个CPU上运行 101
4.4 小结 107
延伸阅读 107
第5章 Windows内核同步机制 108
5.1 基础知识:触发和等待 108
5.1.1 为什么要使用内核对象 110
5.1.2 在非托管代码中执行等待操作 111
5.1.3 托管代码 122
5.1.4 异步过程调用 124
5.2 内核对象的使用 126
5.2.1 互斥体 126
5.2.2 信号量 131
5.2.3 互斥体/信号量使用示例:阻塞/有界的队列 134
5.2.4 自动重置事件和手动重置事件 136
5.2.5 等待定时器 141
5.2.6 触发对象与自动等待 146
5.2.7 内核对象的调试 152
5.3 小结 153
延伸阅读 154
第6章 数据同步与控制同步 155
6.1 互斥 156
6.1.1 Win32临界区 156
6.1.2 CLR锁 166
6.2 读/写锁(RWL) 177
6.2.1 Windows Vista中的轻量级读/写锁 178
6.2.2 .NET框架中的轻量级读/写锁(3.5) 181
6.2.3 .NET框架中原来的读/写锁 185
6.3 条件变量 187
6.3.1 Windows Vista条件变量 187
6.3.2 .NET框架的Monitor 191
6.3.3 被守护区域 192
6.4 小结 193
延伸阅读 193
第7章 线程池 195
7.1 线程池的基本知识 195
7.1.1 三种方式:Windows Vista、Windows遗留代码以及CLR 196
7.1.2 通用功能 197
7.2 Windows线程池 199
7.2.1 Windows Vista线程池 199
7.2.2 遗留的Win32线程池 219
7.3 CLR线程池 226
7.3.1 工作项 226
7.3.2 I/O完成端口 228
7.3.3 定时器 231
7.3.4 注册等待 233
7.3.5 记住(再次提醒):你并不拥有这些线程 234
7.3.6 线程池的线程管理 235
7.3.7 调试 240
7.3.8 案例分析:优先级分层以及在线程池之上的隔离性 241
7.4 在使用线程池时的性能 244
7.5 小结 249
延伸阅读 249
第8章 异步编程模型 251
8.1 异步编程模型(APM) 251
8.1.1 汇集:四种方式 253
8.1.2 实现IAsyncResult 261
8.1.3 在.NET框架的哪些地方使用了APM 265
8.1.4 ASP.NET异步页 265
8.2 基于事件的异步模式 266
8.2.1 基础知识 267
8.2.2 支持取消 269
8.2.3 支持进度报告以及增量结果 269
8.2.4 在.NET框架的哪些地方将使用EAP 270
8.3 小结 270
延伸阅读 271
第9章 纤程 272
9.1 纤程简介 272
优点与缺点 273
9.2 纤程的使用 275
9.2.1 创建新的纤程 275
9.2.2 将线程转换为纤程 277
9.2.3 判断线程是否为纤程 278
9.2.4 纤程间的切换 278
9.2.5 删除纤程 279
9.2.6 切换当前线程的示例 280
9.3 与纤程相关的其他主题 282
9.3.1 纤程局部存储 282
9.3.2 线程关联性 283
9.3.3 案例分析:纤程与CLR 285
9.4 构建用户态的调度器 287
9.4.1 实现 287
9.4.2 关于栈阻塞与无栈阻塞 301
9.5 小结 301
延伸阅读 301
第三部分 技术 303
第l0章 内存模型与无锁编程 303
10.1 内存加载与存储等操作的重新排序 303
10.1.1 实际运行的顺序并非总是编写的顺序 305
10.1.2 将临界域作为栅栏 307
10.1.3 数据依赖性及其对重排的影响 307
10.2 硬件原子性 308
10.2.1 普通加载指令和存储指令的原子性 309
10.2.2 互锁操作 312
10.3 内存一致性模型 322
10.3.1 硬件内存模型 323
10.3.2 内存栅栏 325
10.3.3 .NET内存模型 328
10.3.4 无锁编程 329
10.4 低锁代码的示例 330
10.4.1 延迟初始化与双重检查锁定 330
10.4.2 无阻塞栈和ABA问题 341
10.4.3 重新回顾Dekker的算法 345
10.5 小结 346
延伸阅读 346
第11章 并发的危害 348
11.1 正确性危害 348
11.1.1 数据竞争 348
11.1.2 递归与重入 354
11.1.3 锁与进程关闭 358
11.2 活跃性危害 366
11.2.1 死锁 366
11.2.2 遗失的唤醒 384
11.2.3 活锁 386
11.2.4 锁护送效应 388
11.2.5 “蜂拥”现象 389
11.2.6 两步舞 390
11.2.7 优先级反转与饥饿 391
11.3 小结 392
延伸阅读 392
第12章 并行容器 394
12.1 细粒度锁定 395
12.1.1 数组 395
12.1.2 FIFO队列 396
12.1.3 链表 399
12.1.4 字典(散列表) 403
12.2 无锁 408
12.2.1 无锁FIFO队列 408
12.2.2 工作密迁队列 411
12.3 协作式容器 415
12.3.1 生产者/消费者数据结构 415
12.3.2 通过栅栏来分阶段计算 422
12.4 小结 426
延伸阅读 426
第13章 数据并行与任务并行 427
13.1 数据并行 428
13.2 任务并行 444
13.2.1 分支/合并算法 445
13.2.2 数据流并行(Future抽象与Promise抽象) 447
13.2.3 递归 457
13.2.4 流水线 462
13.2.5 查找 467
13.3 基于消息的并行 468
13.4 一些共同问题 469
13.4.1 并发的异常 469
13.4.2 取消 475
13.5 小结 477
延伸阅读 477
第14章 性能与可伸缩性 478
14.1 并行硬件架构 478
14.1.1 SMP、CMP与HT 478
14.1.2 超标量执行 479
14.1.3 内存的层次结构 480
14.1.4 Visual Studio中的性能分析工具 491
14.2 加速比:并行代码与串行代码 492
14.2.1 决定“采用并行” 492
14.2.2 测量并行带来的性能提升 493
14.2.3 Amdahl定律 496
12.2.4 关键路径以及负载不均衡 497
14.2.5 垃圾收集与可伸缩性 497
14.3 自旋等待 498
14.3.1 如何在Windows上正确地自旋 499
14.3.2 纯自旋锁 502
14.3.3 Mellor-Crummey-Scott(MCS)锁 506
14.4 小结 508
延伸阅读 509
第四部分 系统 511
第15章 输入与输出 511
15.1 重叠I/O 511
15.1.1 重叠对象 512
15.1.2 Win32异步I/O 515
15.1.3 .NET框架的异步I/O 534
15.2 I/O取消 537
15.2.1 当前线程的异步I/O取消 538
15.2.2 其他线程上的同步I/O取消 538
15.2.3 任意线程的异步I/O取消 539
15.3 小结 539
延伸阅读 540
第16章 图形用户界面 541
16.1 GUI线程模型 541
16.1.1 单线程套间(STA) 543
16.1.2 响应度:它是什么 545
16.2 .NET异步GUI功能 545
16.2.1 .NET的GUI框架 546
16.2.2 同步上下文 552
16.2.3 异步操作 558
16.2.4 一个方便的类:BackgroundWorker 559
16.3 小结 561
延伸阅读 562
第五部分 附录 563
附录A 为.NET并发程序设计可重用的库 563
附录B .NET的并行扩展 575