C++并发编程实战(读书笔记)——C++内存模型不好理解;无锁数据结构?但是等待不就是被锁住了吗??

C++并发编程实战

目录

 [隐藏] 
  • 1 基本线程管理
  • 2 在线程间共享数据
  • 3 同步
  • 4 C++内存模型和原子操作
  • 5 基于锁的并发数据结构
  • 6 设计无锁并发数据结构
  • 7 设计并发代码
  • 8 高级线程管理
  • 9 多线程应用的测试与调试
  • 10 附录A C++部分语言特性简明参考
  • 11 附录B 并发类库对比
  • 12 附录C 消息传递框架与完整的ATM示例
  • 13 附录D C++线程类库参考

基本线程管理[编辑]

  1. p18 RAII:~thread_guard:if(t.joinable())t.join();
  2. p29 std::this_thread::get_id()

在线程间共享数据[编辑]

  1. mutex
    1. p36 std::lock_guard l(m); //RAII风格
    2. p45 std::lock可以用时锁住2个或更多的mutex?
    3. p46 让每个线程仅持有一个锁,--> 但是仍然有可能相互等待...
    4. p50 层次锁?
    5. p52 std::unique_lock??
  2. p57 臭名昭著的2次检查锁定模式:data race(~ C++内存模型)
    1. std::call_once(std::once_flag f, std::shared_ptr res);
  3. p60 读写mutex:boost::shared_mutex
  4. p61 递归锁(略)

同步[编辑]

  1. std::condition_variable data_cond;
    1. data_cond.wait( lk, []{return !queue.empty()} );
    2. data_cond.notify_one(); //唤醒一个,注意,上面2句都需要在std::unique_lock的保护范围内(queue是共享变量)
  2. p68 threadsafe_queue?
  3. 使用future等待一次性事件
    1. std::future result = std::async(doWork); //将在result.get()时阻塞
  4. std::packaged_task -> get_future() //高层抽象
  5. std::promise*
    1. set_value / get_future
  6. std::shared_future*
  7. std::chrono::
    1. system_clock, steady_clock, high_resolution_clock
    2. duration
    3. time_point
  8. std::timed_mutex:try_lock_for / try_lock_until
  9. p91 基于future的parallel_quick_sort
  10. p92 spawn_task
    1. typedef std::result_of::type result_type; //?

C++内存模型和原子操作[编辑]

  1. std::atomic_flag f = ATOMIC_FLAG_INIT;
    1. lock: while(f.test_and_set(std::memory_order_acquire)); //可以运行时切换std::memory_order_*参数到底是个什么鬼??
    2. unlock: fl.clear(std::memory_order_release);
  2. 更通用的std::atomic
    1. b.compare_exchange_weak(expected_value, memory_order_acq_rel, memory_order_acquire); //?
  3. std::atomic上的操作
    1. p108 p.fetch_add(3, std::memory_order_release);
  4. std::atomic
    1. UDT必须有平凡的拷贝赋值(且必须是编译器默认生成的,POD?)、必须是按位相等可比较的
  5. 原子操作函数*
  6. p114 happens-before和synchronizes_with
  7. p116 6种内存顺序:
    1. 代表了3种模型:
      1. 顺序一致(最容易理解的,但在多处理器但弱顺序机器上有性能问题)
      2. 非顺序一致:*
        1. ?唯一的要求是所有的线程对每个独立变量的修改顺序达成一致(“达成一致”指的是什么意思???)
      3. 松弛:原子类型上但操作不参与synchronizes_with关系,单线程中的同一个变量的操作仍然服从happens-before关系
      4. p124 获得-释放:靠,仍然有点费解
      5. 获取-释放顺序传递性同步*
      6. p130 memory_order_consume:数据依赖(?)
  8. p133 释放序列和synchronizes_with **
  9. 内存屏障
    1. p137 用原子操作排序非原子操作*

基于锁的并发数据结构[编辑]

  1. p162 设计一个细粒度的map数据结构
    1. RB-tree(std::map)从访问根节点开始,... 尽管线程沿着树往下移动的时候会释放这个锁 ...
    2. 已排序数组
    3. hashmap:可以在每个桶上有一个独立的锁
  2. p165 编写一个使用锁的线程安全链表
    1. 基本思想是每个节点使用一个mutex(细粒度锁)... ?如果要修改相邻的2个节点,需要同时上锁吧?
    2. 可以参考Linux Kernel里的list实现...

设计无锁并发数据结构[编辑]

  1. p174 无锁的线程安全栈*
    1. 不是无等待的!(线程死循环忙等不就相当于被“锁住”了吗?)
    2. p178 管理内存(防止泄露):你想释放一个节点,但必须确保没有别的线程引用时才能这么做,... 这从根本上意味着需要为节点写一个专用GC
    3. p182 用风险指针(hazard pointers)检测不能回收的节点 *
    4. p189 使用引用计数检测节点 *
    5. p194 将内存模型应用至无锁栈 *
  2. p198 无锁队列
  3. 编写无锁数据结构的准则
    1. p210 使用std::memory_order_seq_cst
    2. 使用无锁内存回收模式
    3. 当心ABA问题
    4. 识别忙于等待的循环及辅助其他线程

设计并发代码[编辑]

  1. p219 以任务类型划分工作
  2. p221 划分线程间的任务队列(管道)
  3. 影响性能的因素
    1. p223 数据竞争和缓存乒乓
    2. 假共享(CPU的片内cache line)
  4. 额外考虑
    1. p230 并行算法中的异常安全 *
  5. 在实践中设计并发代码:STL算法的并行实现 **
    1. std::for_each
    2. std::find
    3. std::partial_sum

高级线程管理[编辑]

  1. 线程池
  2. 中断线程(这里的思想似乎来自于Java interrupt()?)

多线程应用的测试与调试[编辑]

  1. 不必要的阻塞:死锁、活锁、IO阻塞
  2. 竞争条件
  3. 多线程测试
    1. ps:Google Android上的Address Sanitizer (ASAN)工具?

附录A C++部分语言特性简明参考[编辑]

附录B 并发类库对比[编辑]

附录C 消息传递框架与完整的ATM示例[编辑]

附录D C++线程类库参考

你可能感兴趣的:(读书笔记)