当使用 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. 一、关于EF你不知道的事

    一.EF 1. 只做查询 ,不用做修改时可以用,提高EF查询性能 var list = db.Users.AsNoTracking().First(x=>x.Name).ToList();

  2. Python——字符格式化

    一.分类:%格式符方式,format方式 二.%格式符 1.%s——字符占位,%d——数字占位(十进制) a = ("%(name)s--%(age)d" % {'name':'x ...

  3. Lodop打印表格带页头页尾 自动分页每页显示头尾

    Lodop中有两种专门给超文本表格的方式,ADD_PRINT_TABLE和ADD_PRINT_TBURL,该方式只能用于单个表格,表格外的内容不显示,是专门用于打印html超文本表格的.使用这两个语句 ...

  4. aop通知加参数的匹配规则

  5. BZOJ 3669 魔法森林

    LCT维护生成树 先按照a的权值把边排序,离线维护b的最小生成树. 将a排序后,依次动态加边,我们只需要关注b的值.要保证1-n花费最少,两点间的b值肯定是越小越好,所以我们可以考虑以b为关键字维护最 ...

  6. Lua语法基础(一)

    1. 注释 -- 单行注释 --[[ 多行注释 --]] 2. 运行方式     (1)交互式运行         命令行下 lua进入交互模式     (2)命令行运行         lua + ...

  7. COGS 2353 2355 2356 2358 有标号的DAG计数

    不用连通 枚举入度为0的一层 卷积 发现有式子: 由$n^2-i^2-(n-i)^2=2*i*(n-i)$ 可得$2^{i*(n-i)}=\frac{{\sqrt 2}^{(n^2)}}{{\sqrt ...

  8. CF55D Beautiful numbers

    题目链接 题意 定义一个数字\(x\)是\(beautiful\ number\)当且仅当\(x\)可以被其十进制表示下所有非\(0\)位置的数整除. 例如\(24\)是一个\(beautiful\ ...

  9. Codeforces Round #553 (Div. 2)

    传送门 A. Maxim and Biology 题意: 给出一个串s,问最少需要多少步操作使得串s包含"ACTG"这个子串,输出最少操作次数: 题解: 枚举每个位置 i,求出将 ...

  10. GDB disassemble

    前面几篇谈GDB调试程序的帖子,都对反汇编语焉不详.这里详细讨论一下disassemble/disass命令 反汇编一个函数disass func_name 反汇编一段内存地址, 第1个参数是起始地址 ...