当使用 std::thread 对象执行线程时,必须要调用 join() (或者 detach(),由于 detach() 可以立即调用,所以这里只考虑 join())

 #include <iostream>
#include <thread>
#include <chrono> using namespace std; void threadInvoker()
{
cout << "thread begin\n";
this_thread::sleep_for(chrono::milliseconds());
cout << "thread end\n";
} void doSomething()
{
cout << "doSomething begin\n";
this_thread::sleep_for(chrono::milliseconds());
cout << "doSomething end\n";
} void doOther()
{
} void f()
{
thread t(threadInvoker); doSomething(); doOther();
t.join();
} int main()
{
f();
}

编译:g++ -std=c++11 -pthread test.cpp

如果 doSomething() 会产生异常,则尝试捕获

 #include <iostream>
#include <thread>
#include <chrono> using namespace std; void threadInvoker()
{
cout << "thread begin\n";
this_thread::sleep_for(chrono::milliseconds());
cout << "thread end\n";
} void doSomething()
{
cout << "doSomething begin\n";
this_thread::sleep_for(chrono::milliseconds());
throw ;
cout << "doSomething end\n";
} void doOther()
{
} void f()
{
thread t(threadInvoker); try {
doSomething();
}
catch (...) {
cout << "catch exception\n";
t.join();
return;
} doOther();
t.join();
} int main()
{
f();
}

但是必须在 catch 块里调用 t.join(),否则会 crash。如果条件一多,很可能会在某个分支下遗忘 t.join()。

因此可以使用 RAII 来避免,在析构函数中进行 join()

 #include <iostream>
#include <thread>
#include <chrono> using namespace std; class ThreadGuard
{
public:
explicit ThreadGuard(thread& t):mT(t) {}
~ThreadGuard()
{
if (mT.joinable()) {
cout << "join\n";
mT.join();
}
}
ThreadGuard(ThreadGuard const&) = delete;
ThreadGuard& operator=(ThreadGuard const&) = delete;
private:
thread& mT;
}; void threadInvoker()
{
cout << "thread begin\n";
this_thread::sleep_for(chrono::milliseconds());
cout << "thread end\n";
} void doSomething()
{
cout << "doSomething begin\n";
this_thread::sleep_for(chrono::milliseconds());
throw ;
cout << "doSomething end\n";
} void doOther()
{
} void f()
{
thread t(threadInvoker);
ThreadGuard tg(t); try {
doSomething();
}
catch (...) {
cout << "catch exception\n";
return;
} doOther();
} int main()
{
f();
}

利用局部对象的析构保证 join() 的调用

使用 RAII 完成线程等待的更多相关文章

  1. SQL之收集SQL Server线程等待信息

    要知道线程等待时间是制约SQL Server效率的重要原因,这一个随笔中将学习怎样收集SQL Server中的线程等待时间,类型等信息,这些信息是进行数据库优化的依据. sys.dm_os_wait_ ...

  2. 对线程等待函数pthread_join二级指针参数分析

    分析之前先搞明白,这个二级指针其实在函数内部是承接了上个线程的返回值. 看man手册,发现返回值是个普通指针.人家用二级指针来承接,可能准备干大事.这个可以自己搜索一下.原因嘛,二级指针是保存了这个地 ...

  3. Java多线程系列--“基础篇”05之 线程等待与唤醒

    概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...

  4. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  5. 收集SQLServer线程等待信息

    要知道线程等待时间是制约SQL Server效率的重要原因,这一个随笔中将学习怎样收集SQL Server中的线程等待时间,类型等信息,这些信息是进行数据库优化的依据. sys.dm_os_wait_ ...

  6. SQL点滴13—收集SQLServer线程等待信息

    原文:SQL点滴13-收集SQLServer线程等待信息 要知道线程等待时间是制约SQL Server效率的重要原因,这一个随笔中将学习怎样收集SQL Server中的线程等待时间,类型等信息,这些信 ...

  7. c/c++ 多线程 多个线程等待同一个线程的一次性事件

    多线程 多个线程等待一个线程的一次性事件 背景:从多个线程访问同一个std::future,也就是多个线程都在等待同一个线程的结果,这时怎么处理. 办法:由于std::future只能被调用一次get ...

  8. c/c++ 多线程 一个线程等待某种事件发生

    多线程 一个线程等待某种事件发生 背景:某个线程在能够完成其任务之前可能需要等待另一个线程完成其任务. 例如:坐夜间列车,为了能够不坐过站, 1,整夜保持清醒,但是这样你就会非常累,不能够睡觉. 2, ...

  9. 第三节:ThreadPool的线程开启、线程等待、线程池的设置、定时功能

    一. ThreadPool简介 ThreadPool简介:ThreadPool是一个线程池,当你需要开启n个线程时候,只需把这个指令抛给线程池,它将自动分配线程进行处理,它诞生于.Net 2.0时代. ...

随机推荐

  1. RazorEngine

    目标 使用razorengine编译cshtml页面生静态html 制作一个vs2017的插件,实现右击cshtml文件时,编译该文件. 环境 razorengine4.5 / netframewor ...

  2. webpack学习记录-认识loader(二)

    Loader 就像是一个翻译员,能把源文件经过转化后输出新的结果,并且一个文件还可以链式的经过多个翻译员翻译. loader参考文章:https://webpack.docschina.org/loa ...

  3. 微服务与容器化Docker

    1.Docker的应用案例 2. 3. 4.docker的核心:镜像.仓库.容器 Build构建镜像:类似于集装箱. Ship运输镜像,仓库:类似于码头.将镜像运输到仓库. Run运行镜像:容器:类似 ...

  4. Tomcat 服务器

    1 相关概念 1 软件的架构 1 c/s 客服端/服务端 2 b/s 浏览器/服务器 2 资源的分类 1 静态资源 所有用户访问后 得到的资源是一样的 称为静态资源 html css js 静态资源可 ...

  5. MySQL_表锁_lock tables tableName read

    pre.环境准备 1.建立两个表S,T,并插入一些数据 --创建表S create table S(d int) engine=innodb; ); --创建表T create table T(c i ...

  6. Docker:dockerfile镜像的分层 [九]

    一.docker镜像的分层 1.图像呈现 2.命令呈现 [root@oldboy kod]# docker image history kod:v1 IMAGE CREATED CREATED BY ...

  7. ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树+LCA)

    https://nanti.jisuanke.com/t/31462 题意 一个N*M的矩形,每个格点到其邻近点的边有其权值,需要构建出一个迷宫,使得构建迷宫的边权之和最小,之后Q次查询,每次给出两点 ...

  8. HDU 1584(蜘蛛牌 DFS)

    题意是在蜘蛛纸牌的背景下求 10 个数的最小移动距离. 在数组中存储 10 个数字各自的位置,用深搜回溯的方法求解. 代码如下: #include <bits/stdc++.h> usin ...

  9. 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法

    一. 背景 上一个章节,介绍了EF调用两类SQL语句,主要是借助 ExecuteSqlCommand  和 SqlQuery 两个方法来完成,在本章节主要是复习几类存储过程的写法和对应的EF调用这几类 ...

  10. 使用kqueue的str_cli函数

    void str_cli(FILE *fp, int sockfd) { , isfile; char buf[MAXLINE]; ]; struct timespec ts; struct stat ...