7 设计无锁的并发数据结构
7.1 定义和结果
7.1.1 非阻塞数据结构的类型
7.1.2 无锁数据结构
7.1.3 无等待的数据结构
7.1.4 无锁数据结构的优点与缺点
7.2 无锁数据结构的例子
7.2.1 编写不用锁的线程安全栈
7.2.2 停止恼人的泄漏:在无锁数据结构中管理内存
7.2.3 用风险指针检测不能被回收的结点
7.2.4 使用引用计数检测结点
7.2.5 将内存模型应用至无锁栈
7.2.6 编写不用锁的线程安全队列
7.3 编写无锁数据结构的准则
7.3.1 准则:使用std::memory_order_seq_cst作为原型
7.3.2 准则:使用无锁内存回收模式
7.3.3 准则:当心ABA问题
7.3.4 准则:识别忙于等待的循环以及辅助其他线程
7.4 小结
8 设计并发代码
8.1 在线程间划分工作的技术
8.1.1 处理开始前在线程间划分数据
8.1.2 递归地划分数据
8.1.3 以任务类型划分工作
8.2 影响并发代码性能的因素
8.2.1 有多少个处理器?
8.2.2 数据竞争和乒乓缓存
8.2.3 假共享
8.2.4 数据应该多紧密
8.2.5 过度订阅和过多的任务切换
8.3 为多线程性能设计数据结构
8.3.1 为复杂操作划分数组元素
8.3.2 其他数据结构中的数据访问方式
8.4 为并发设计时的额外考虑
8.4.1 并行算法中的异常安全
8.4.2 可扩展性和阿姆达尔定律
8.4.3 用多线程隐藏延迟
8.4.4 用并发提高响应性
8.5 在实践中设计并发代码
8.5.1 std::for_each的并行实现
8.5.2 std::find的并行实现
8.5.3 std::partial_sum的并行实现
8.6 总结
9 高级线程管理
9.1 线程池
9.1.1 最简单的线程池
9.1.2 等待提交给线程池的任务
9.1.3 等待其他任务的任务
9.1.4 避免工作队列上的竞争
9.1.5 工作窃取
9.2 中断线程
9.2.1 启动和中断另一个线程
9.2.2 检测一个线程是否被中断
9.2.3 中断等待条件变量
9.2.4 中断在std::condition_variable_any上的等待
9.2.5 中断其他阻塞调用
9.2.6 处理中断
9.2.7 在应用退出时中断后台任务
9.3 总结
附录D C++线程类库参考
D.1 <chrono>头文件
D.1.1 std::chrono::duration类模板
D.1.2 std::chrono::time_point类模板
D.1.3 std::chrono::system_clock类
D.1.4 std::chrono::steady_clock类
D.1.5 std::chrono::high_resolution_clock typedef
D.2 <condition_variable>头文件
D.2.1 std::condition_variable类
D.2.2 std::condition_variable_any类
D.3 <atomic>头文件
D.3.1 std::atomic_xxx typedef
D.3.2 ATOMIC_xxx_LOCK_FREE宏
D.3.3 ATOMIC_VAR_INIT宏
D.3.4 std::memory_order枚举
D.3.5 std::atomic_thread_fence函数
D.3.6 std::atomic_signal_fence函数
D.3.7 std::atomic_flag类
D.3.8 std::atomic类模板
D.3.9 std::atomic模板的特化
D.3.10 std::atomic<integral-type>特化
D.3.11 std::atomic<T*>偏特化
D.4 <future>头文件
D.4.1 std::future类模板
D.4.2 std::shared_future类模板
D.4.3 std::packaged_task类模板
D.4.4 std::promise类模板
D.4.5 std::async函数模板
D.5 <mutex>头文件
D.5.1 std::mutex类
D.5.2 std::recursive_mutex类
D.5.3 std::timed_mutex类
D.5.4 std::recursive_timed_mutex类
D.5.5 std::lock_guard类模板
D.5.6 std::unique_lock类模板
D.5.7 std::lock函数模板
D.5.8 std::try_lock函数模板
D.5.9 std::once_flag类
D.5.10 std::call_once函数模板
D.6 <ratio>头文件
D.6.1 std::ratio类模板
D.6.2 std::ratio_add模板别名
D.6.3 std::ratio_subtract模板别名
D.6.4 std::ratio_multiply模板别名
D.6.5 std::ratio_divide模板别名
D.6.6 std::ratio_equal类模板
D.6.7 std::ratio_not_equal类模板
D.6.8 std::ratio_less类模板
D.6.9 std::ratio_greater类模板
D.6.10 std::ratio_less_equal类模板
D.6.11 std::ratio_greater_equal类模板
D.7 <thread>头文件
D.7.1 std::thread类
D.7.2 this_thread命名空间
3 在线程间共享数据
3.1 线程之间共享数据的问题
3.1.1 竞争条件
3.1.2 避免有问题的竞争条件
3.2 用互斥元保护共享数据
3.2.1 使用C++中的互斥元
3.2.2 为保护共享数据精心组织代码
3.2.3 发现接口中固有的竞争条件
3.2.4 死锁:问题和解决方案
3.2.5 避免死锁的进一步指南
3.2.6 用std::unique_lock灵活锁定
3.2.7 在作用域之间转移锁的所有权
3.2.8 锁定在恰当的粒度
3.3 用于共享数据保护的替代工具
3.3.1 在初始化时保护共享数据
3.3.2 保护很少更新的数据结构
3.3.3 递归锁
3.4 小结
5 C++内存模型和原子类型上操作
5.1 内存模型基础
5.1.1 对象和内存位置
5.1.2 对象、内存位置以及并发
5.1.3 修改顺序
5.2 C++中的原子操作及类型
5.2.1 标准原子类型
5.2.2 std::atomic_flag上的操作
5.2.3 基于std::atomic<bool>的操作
5.2.4 std::atomic<T*>上的操作:指针算术运算
5.2.5 标准原子整型的操作
5.2.6 std::atomic<>初级类模板
5.2.7 原子操作的自由函数
5.3 同步操作和强制顺序
5.3.1 synchronizes-with关系
5.3.2 happens-before关系
5.3.3 原子操作的内存顺序
5.3.4 释放序列和synchronizes-with
5.3.5 屏障
5.3.6 用原子操作排序非原子操作
5.4 小结