c++11开始支持多线程编程,相关的类和函数封装在标准库头文件<thread>中,而c++多线程编程很重要的一点就是当用户创建一个std::thread对象,关联了可调用对象后,需要在该thread对象销毁前调用join()或detach()。其中join()函数用于结合线程,确保在创建该thread对象的函数退出前,该线程执行完毕;而detach()函数则表示分离线程,即让线程在后台运行,线程的所有权和控制权交给c++运行时库。若thread对象销毁前没有调用join()或detach(),则程序会被终止(thread的析构函数调用std::terminate() )。

如果用户要分离线程,那么一般情况下在线程启动后立即调用detach()即可。但若需要等待线程,那么调用join()的时机就很重要:如果线程在开始之后、调用join()之前发生了异常,则join()的调用就会被跳过。保证线程在异常环境下的等待的方法之一是使用try/catch语句块:

 1 #include <thread>
 2 #include <stdexcept>
 3
 4 using std::thread;
 5 using std::runtime_error;
 6
 7 void func();
 8
 9 void TestThread() {
10     thread thrd(func);
11     try
12     {
13         //...
14     }
15     catch (runtime_error re)
16     {
17         thrd.join();
18         throw re;
19     }
20     thrd.join();
21 }

但是很显然,使用try/catch语句块很罗嗦,且容易将作用域弄乱。一个更好的方法是使用资源获取即初始化(Resource Acquisition Is Initialization, RAII)的方法,RAII是C++的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII 的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源。

使用RAII的代码如下:

 1 #include <thread>
 2
 3 using std::thread;
 4
 5 void func();
 6
 7 class Thread_RAII {
 8 private:
 9     thread &thrd;
10 public:
11     explicit Thread_RAII(thread &p_thrd) : thrd(p_thrd) {}
12     ~Thread_RAII()
13     {
14         if (thrd.joinable())
15         {
16             thrd.join();
17         }
18     }
19     Thread_RAII(const Thread_RAII &) = delete;
20     Thread_RAII & operator=(const Thread_RAII &) = delete;
21 };
22
23 void TestThread()
24 {
25     thread thrd(func);
26     Thread_RAII tr(thrd);
27     //...
28 }

当函数TestThread()执行到末尾时,局部对象按照构造的逆序进行销毁,因此tr首先被销毁,于是其中的thrd对象被结合,即使在之前其中的某条语句执行时引发异常而退出时也是如此。

上述代码还有两点需要注意:

①析构函数在调用join()之前需要检查thrd是否是joinable()的,因为对于一个线程,join()只能调用一次。

②Thread_RAII类的拷贝构造函数及拷贝复制运算符是删除的,这是因为thread对象和unique_ptr一样是不可拷贝的(但可以移动)。

转载于:https://www.cnblogs.com/jzincnblogs/p/5179749.html

c++多线程在异常环境下的等待相关推荐

  1. 多线程环境下,程序真是危机四伏

    姿势在不断的更新迭代, 太卷了. 你管这也叫线程安全? 最近大意了,竟然想将<面试官:实现一个带值变更通知能力的Dictionary>一文中的临界锁只应用到写操作. 内心旁白:读操作又不会 ...

  2. 分布式环境下,互斥性与幂等性问题,分析与解决思路

    欢迎关注方志朋的博客,回复"666"获面试宝典 随着互联网信息技术的飞速发展,数据量不断增大,业务逻辑也日趋复杂,对系统的高并发访问.海量数据处理的场景也越来越多.如何用较低成本实 ...

  3. 多线程编程之Linux环境下的多线程(三)——好文

    http://www.cnblogs.com/kuliuheng/p/4063892.html 前面两篇文章都讲述了Linux环境下的多线程编程基础知识,也附带了典型实例.本文主要比较一下Linux环 ...

  4. Linux环境下多线程C/C++程序的内存问题诊断

    目录 说明 常见的内存错误举例 常见的内存访问错误有以下几种: 内存问题定位步骤 野指针 内存释放后使用(UaF,Use after Free) 内存问题检查工具 常见的内存问题检查工具 Valgri ...

  5. 分析解决11gR2 双节点RAC环境下的gc cr block busy/gc buffer busy acquire等待

    ?  系统环境 两节点的RAC:AIX6.1+Oracle 11.2.0.3.3 ?  AWR里展示出来的各种症状(数据来自实例2) 虽然应用没有报障,但AWR报告里的各种迹象已经很明显了 (1)   ...

  6. Linux环境下,C++实现龟兔赛跑的多线程编程

    编程 使⽤ Thread 实现多线程编程 题目:龟兔赛跑,跑道距离50米.乌龟(作为⼀个线程) 每秒3米,不睡觉 : 兔子(作为⼀个线程)每秒5米,每跑15⽶睡2秒钟.请模拟比赛情况. #includ ...

  7. Java8环境下使用restTemplate单/多线程下载大文件和小文件

    Java8环境下使用restTemplate单/多线程下载大文件和小文件 0. 准备工作 1. 简单的下载文件 2. 单线程大文件下载 3. 多线程下载 0. 准备工作 下面使用的restTempla ...

  8. 项目总结10:通过反射解决springboot环境下从redis取缓存进行转换时出现ClassCastException异常问题...

    通过反射解决springboot环境下从redis取缓存进行转换时出现ClassCastException异常问题 关键字 springboot热部署  ClassCastException异常 反射 ...

  9. java中HashMap在多线程环境下引起CPU100%的问题解决

    最近项目中出现了Tomcat占用CPU100%的情况,原以为是代码中出现死循环,后台使用jstack做了dump,发现是系统中不合理使用HashMap导致出现了死循环(注意不是死锁). 产生这个死循环 ...

  10. Struts2环境下Tomcat启动异常:Exception starting filter struts2,报了一个java.lang.ClassNotFoundException

    Struts2环境下Tomcat启动异常:Exception starting filter struts2,报了一个java.lang.ClassNotFoundException 参考文章: (1 ...

最新文章

  1. C/C++之变长数组(VLA)和可伸缩型数组成员
  2. jboss8日志级别设置_罐中研讨会:设置JBoss BRMS全日研讨会
  3. ASP.NET之Ajax系列(三)
  4. MySQL学习记录 (二) ----- SQL数据查询语句(DQL)
  5. linux安装nsenter工具,Docker 使用nsenter工具进入容器的操作
  6. xcode中遇到的英文名词(更新)
  7. 如何在CAD中输入带圈序号?
  8. 上海市计算机二级vb试题及答案,上海市207计算机二级vb试题.doc
  9. 基于javaweb的驾校车辆教练预约系统ssm+Vue
  10. 4款最受欢迎的Mac原型工具
  11. 有两个水桶,一个可装7升水,一个装水3升,怎样量出2升
  12. dlang语法的简单整理
  13. 2021年超全超详细的最新大数据开发面试题,附答案解析
  14. 国产ChatGPT命名图鉴
  15. 关于C++ variant 类型问题
  16. 【FPGA】五、蜂鸣器播放音乐
  17. 我的第一个JDBC小项目
  18. 3月16日---3月20日课程表
  19. 企业自动化办公之请假单-下篇
  20. 【H264解析Demo】10、变换量化_3_反变换

热门文章

  1. 兼容性测试中如何切换和管理多个JDK版本
  2. 51NOD 1181 质数中的质数(质数筛法)
  3. javasript深度拷贝
  4. 15个顶级多线程面试题及答案
  5. sublime 执行print带有中文时出错Decode error - output not utf-8
  6. 哈希表(散列表)冲突解决方法
  7. pptp,l2tp获取登录用户信息用pppd参数即可
  8. java路径两种写法/和\\
  9. 1-5Badboy添加检查点和参数化
  10. 使用charles抓取https的方法