FOUR:tonbu 并发操作
发布日期:2021-06-29 18:56:11
浏览次数:2
分类:技术文章
本文共 2003 字,大约阅读时间需要 6 分钟。
文章目录
- 等待事件
- 用 future来等待一次性事件
- 有时间限制的等待
- 用操作的同步来简化代码
- 上章
- 各种方法保护在线程间共享的数据
- 但有时你不只需保护数据
- 还需在独立的线程上同步操作
- 一个线程在能够完成其任务之前可能需等待另一个线程完成任务
- 希望一个线程等待特定事件的发生或
- 是一个条件变为true是常见的事情
- 虽然通过定期检查“任务完成”的标识或是在共享数据中存储类似的东西也能够做到这一点,但不理想
- 这样的线程间同步操作的需求常见
- C++标准库提供以条件変量和期值为形式的工具来处理它
- 如何用条件变量和期值来等待事件
- 如何用它们来简化操作的同步
4.1等待事件或其他条件
- 你正乘坐通宵列车旅行。
- 理想的状况是,你只管去睡觉,让某个人或某个东西在火车到站时叫醒你,无论何时
- 如果一个线程正等待着第二个线程完成一项任务,
- 它有几个选择
- 它可一直检查共享数据(由互斥元保护)中的标识
- 且让第1个线程在完成任务时设置该标识
- 两浪费,线程占用了宝贵的处理时间去反复检查该标识
- 当互斥元被等待的线程锁定后,就不能被任何其他线程锁定。
- 两者都反对线程进行等待,
- 它们限制了等待中的线程的可用资源,
- 甚至阻止它在完成任务时设置标识
- 整夜保持清醒地与司机交谈,
- 他不得不把火车开得更慢,
- 因为你一直在干扰他,所以需更长的时间オ能到达
- 等待中的线程消耗了本可以被系统中其他线程使用的资源,
- 且最终等待的时间可能会比所需的更长
- 第二个选择
- 用std::this_thread::sleep_for()(4.3节)
- 让等待中的线程在检査之间休眠一会儿。
- 这个循环里,函数在休眠之前②解锁该互斥元,并在之后再次锁定之③,所以另一个线程有机会获取它并设置标识。
- 线程在休眠时并不浪费处理时间,但得到正确的休眠时间是很难的。
- 检查之间休眠得过短,线程仍然会浪费处理时间进行检查;
- 休眠得过长,即使线程正在等待的任务已经完成,它还会继续休眠,导致延迟。
- 这种过度休眠很少直接影响程序的操作,但它可能意味着在快节奏的游戏中丢帧,或者在实时应用程序中过度运行一个时间片。
- 用C标准库提供的工具来等待事件本身
- 等待由另一个线程触发一个事件的最基本机制
- (如前面提到的管道中存在的额外操作)
- 是条件变量
- 条件变量与某些事件或其他条件相关
- 且一个或多个线程可等待该条件被满足
- 当某线程已经确定条件得到满足
- 它就可通知一个或多个正在条件变量上等待的线程
- 唤醒它们并让它们继续
4.1.1用条件变量等待条件
-
标准C++库提供两个条件变量的实现
- condition_variable
- condition_variable_any。
- <condition_variab1e>头文件
-
两者都需和互斥元一起工作,以便提供恰当同步
-
前者仅限和std::mutex一起工作
-
后者
- 可与符合成为类似互斥元的最低标准的任何东西一起工作
- 所以有大小、性能或者操作系统资源方面的形式的额外代价的可能
-
首选前,除非需要额外灵活性
- 怎么让正在等待工作的线程休眠,直到有数据要处理?
- 清单4.1展示一种方法,
- 你可用条件变量来实现这一点
- 一个用来在两个线程之间传递数据的队列
- 数据就绪时,
- 准备数据的线程用std:lock_guard
- 去锁定保护队列的互斥元,且将数据压入队列2
- 它在condition_variable的实例上调成员函数,
- 通知等待中的线程(如果有的话)
- 你还有处理线程
- 先锁定互斥元,但用std: unique_lock
- 很快就会明白为什么
- 接下来在std: condition variable上调wait()
- 传入锁对象
- 以及表示正在等待的条件的 lambda函数5
- lambda函数允许你编写一个匿名函数作为另一个表达式的一部分,
- 适合于为类似于wait(O这样的标准库函数指定断言。
- 5
- 检査 data queu是否不为 empty()
- 即队列中已有数据准备处理
- A.5节更加详细地描述lambda函数
- wait()的实现
- 接下来检査条件(lambda函数),满足时返回(lambda返true)
- 如果条件不满足
- wait()解锁互斥元,并将该线程置于阻塞或等待状态
- 当来自数据准备线程中对notify one()的调用通知条件变量时
- 线程从睡眠状态中苏醒(解除其阻塞),重新获得互斥元上的锁,
- 再次检査条件,如果条件已经满足,就从wait()返回值,互斥元仍被锁定
- 如果条件不满足,该线程解锁互斥元,并恢复等待
- 这就是为什么要unique_lock而不是
- 等待中的线程在等待期间必须解锁互斥元,
- 并在这之后重新将其锁定lock_guard没有提供这样的灵活性
- 如果互斥元在线程体眠期间始终被锁定,
- 数据准备线程将无法锁定该互斥元,
- 以便将项目添加至队列,
- 且等待中的线程将永远无法看到其条件得到满足
转载地址:https://cyj666.blog.csdn.net/article/details/109628196 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
第一次来,支持一个
[***.219.124.196]2024年04月03日 23时03分22秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
音频硬件基础
2019-04-30
TS流分析
2019-04-30
详解YUV420数据格式
2019-04-30
Gstreamer学习笔记(2):GstElement定义、连接
2019-04-30
GStreamer建议的学习步骤和网页链接汇总
2019-04-30
Ubuntu14.04编译安装GStreamer
2019-04-30
GStreamer(一)
2019-04-30
GStreamer(二)
2019-04-30
Gstreamer学习笔记(1):GStreamer Debugging
2019-04-30
bitbake常用命令
2019-04-30
Git学习(一):git 生成 patch的命令
2019-04-30
Gstreamer学习笔记(8):Gobject类对象
2019-04-30
Gstreamer学习笔记(7):plugin注册流程分析(超详细)
2019-04-30
Gstreamer学习笔记(6):如何创建gstreamer插件?
2019-04-30
AVI封装格式解析
2019-04-30
rmvb 文件格式解析
2019-04-30
C语言:setjmp和longjmp函数使用详解
2019-04-30
FFmpeg常用基本命令
2019-04-30
MPG(MPEG2 Program Stream)格式解析
2019-04-30