第4章 同步并发操作
线程等待特定事件的发生。
4.1 等待事件或其他条件
几个选择:
1. 一直检查共享数据,
产生浪费: a. 占用时间
b. 当互斥元被等待线程锁定,就不能被任何其他线程锁定
2.使用std::this_thread::sleep_for函数
3.首选:
使用条件变量
4.1.1 用条件变量等待
std::condition_variable
std::condition_variable_any
程序实例分析: 使用队列在线程之间传输数据
1. 对于准备数据的线程
首先:
然后:
2. 对于处理数据的线程
4.1.2 使用条件变量简历一个线程安全队列
—————— 打前站: 第六章 设计并发数据结构
条件变量的使用场合:
1. 多个线程等待,但只有一个线程响应
notify_one
2. 多个线程等待,都需要进行响应
notify_all
限定:只需要等待一次,引出下一小节:
4.2 使用future 等待一次性事件
unique_future 和 shared_future
最基本的一次性事件在后台运行返回结果:
4.2.1 后台任务返回值
异步任务
std::async
三种延迟选项: std::launch::deferred
std::launch::async
std::launch::deferred | std::launch::async
和std::future关联的三种方式
1. std::async
2. std::promise
3. std::packaged_task 最高层次的抽象,引出下一小节:
4.2.2 将任务和future相关联
std::packaged_task将future绑定到一个函数或可调用对象上。
用途:
1. 线程池构件 ———— 第九章
2. 其他任务管理模式
用法 :
1.封装入一个std::function对象
2.传给需要可调用对象的另一个函数
3.干脆直接调用
程序示例:
在线程之间传递任务
另外的情形:
1.无法用一个简单函数调用表达的任务
2.结果可能不来自于一个地方的任务
引出下一小节:
4.2.3 生成std::promise
(没看懂 ……………… )
4.2.4 为future保存异常
1. future保存异常
a. std::async引发
b. std::packaged_task引发
2. promise保存异常
a. set_exception
b. std::copy_exception
3.销毁与future相关联的std::packaged_task 和std::promise
多个线程等待同一个事件:shared_future
4.2.5 等待自多个线程
有时候,需要限制等待事件的时长
4.3 有时间限制的等待
两类超时:
1. 基于时间段:时间长度
2. 绝对超时: 时间点
4.3.1 时钟
4.3.2 时间段
4.3.3 时间点
4.3.4 接受超时的函数
现在,已经有了 条件变量,future,promise,packaged_task 四个工具,
来综合运用一下:
4.4 使用操作同步来简化代码
简化代码的方式:函数式编程
不在线程之间共享数据,通过future将结果进行传递
4.4.1 带有future的函数式编程
1. FP风格快速排序: 只使用FP风格
2. FP风格并行快速排序: 使用future的FP风格
a. 使用std::async
b. 进一步:package_task , 线程池
c. 退一步:回到parallel_quick_sort
函数式编程并非唯一范式,另有CSP:通信顺序处理
4.4.2 具有消息传递的同步操作
有限状态机模型
消息队列
程序示例:ATM
4.5 小结
--
修改:CyberPunker FROM 203.218.252.*
FROM 203.218.252.*