std thread
不要用std::thread写裸线程
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/daan_112211/article/details/19088605
我们先看一段代码:
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
volatile bool flag = false;
void f1() {
for (int i = 0; i < 1000; ++i) {
if (flag) cout << i << " catched" << endl;
else cout << i << " running" << endl;
usleep(10000);
}
}
void f2() {
sleep(1);
flag = true;
throw 1;
}
void run1() {
thread thr(f1);
f2();
thr.join();
}
int main()
{
try {
run1();
} catch(...) {
}
while(1);
}
这段代码中,我们在run1里面发射了一个线程f1,f1是做一个计数工作,在run1里面运行f2,f2在休眠1秒之后抛异常。
运行结果是: 当f2抛异常之后,程序就挂掉了。
这是为什么呢?因为在f2抛出异常之后,run1发生调用栈回退的时候,析构thr了。在析构thr的时候,我们可以看一下gcc的源代码:
~thread()
{
if (joinable())
std::terminate();
}
一旦这个句柄是没有join就调用析构函数,那么调用std::terminate(),这就是程序挂掉的原因。
到这里,似乎就引入了一个疑问,到底这个时候析构了thr,我们更希望发射出来的线程f2应该怎么运行呢?真的希望程序挂掉吗?
分析起来,大致可以有下面两种看起来合理的情况:
1、我们可能希望调用栈回退的时候,等f2运行完,join之后,才完成调用栈回退
2、我们可能希望把f2剥离句柄thr的控制,自己单独运行
这上面两种情况都是可以实现的,我们分别都看一下。我们先来看第一种实现:
class SafeThread {
private:
std::thread thr_;
public:
template< class Function, class... Args >
explicit SafeThread(Function&& f, Args&&... args) {
std::thread thr(f, args ...);
thr_.swap(thr);
}
~SafeThread() {
thr_.join();
}
};
通过这么实现,放到第一段代码的情境中,就会是这样子:
void run1() {
SafeThread thr(f1);
f2();
}
这是RAII的实现方式,在离开作用域的时候析构,而我们在析构的时候完成join的工作。那么,在发生刚才那种情况的时候,异常一旦抛出,run1就要做栈回退,当调用thr的析构函数的时候,自然就会join,等待f1的执行完毕。
接着我们看一下第二种实现:
class SafeThread {
//...同上一种
~SafeThread() {
thr_.detach();
}
};
大部分和第一种实现一样,不同之处在于,当调用析构函数的时候,把线程剥离句柄(就像脱缰的野马)
最后分析一下两种方式的
1、第一种方式,可以像原有逻辑一样,在完成f1线程之后,才结束run1函数。但是,无法及时处理异常
2、第二种方式很不推荐,一旦f1线程使用了run1提供的局部对象作为运行参数,那么一旦run1调用回退了,局部变量被回收,而f1继续使用,程序就错掉了,能段错误是最好的结局了。
总结,用RAII的方式封装std::thread,按第一种方式实现,是一个不错的选择。
参考:http://akrzemi1.wordpress.com/2012/11/14/not-using-stdthread/
std thread相关推荐
- C++11 新特性之std::thread
C++11 新特性之std::thread 原文:https://blog.csdn.net/oyoung_2012/article/details/78958274 从C++11开始,C++标准库已 ...
- 并发,std::thread
2019独角兽企业重金招聘Python工程师标准>>> std::thread 定义一个线程对象,并管理关联的线程 备注: 你可以使用 thread 对象来观察和管理在应用程序中的 ...
- 【多线程】C++11进行多线程开发 (std::thread)
文章目录 创建线程 std::thread 类 使用join() 使用 detach() 警惕作用域 线程不能复制 给线程传参 传递指针 传递引用 以类成员函数为线程函数 以容器存放线程对象 互斥量 ...
- C++11学习笔记-----线程库std::thread
在以前,要想在C++程序中使用线程,需要调用操作系统提供的线程库,比如linux下的<pthread.h>.但毕竟是底层的C函数库,没有什么抽象封装可言,仅仅透露着一种简单,暴力美 C++ ...
- C++ std::thread 和 std::jthread 使用详解 (含C++20新特性)
目录 std::thread std::thread 构造函数 观察器 操作 std::jthread std::jthread 构造函数 观察器 操作 停止记号处理 管理当前线程的函数 yield( ...
- std::jthread与std::thread的区别
特性上,std::jthread相比std::thread主要增加了以下两个功能: 1.std::jthread对象被destruct时,会自动调用join,等待其所表示的执行流结束. 2.支持外部请 ...
- c++11仔细地将参数传递给线程std::thread
要将参数传递给线程的可关联对象或函数,只需将参数传递给std::thread构造函数. 默认情况下,所有的参数都将复制到新线程的内部存储中. 看一个例子: 给线程传递单个参数 #include < ...
- std::thread 不 join
std::thread 构造之后 使用 detach.就可以了
- C++11并发编程:多线程std::thread
一:概述 C++11引入了thread类,大大降低了多线程使用的复杂度,原先使用多线程只能用系统的API,无法解决跨平台问题,一套代码平台移植,对应多线程代码也必须要修改.现在在C++11中只需使用语 ...
最新文章
- 深度学习的第一性原理!
- vs代码显示波浪线,但没编译错误
- 嵌入式研发人员的核心竞争力浅谈 .
- hdu5692 Snacks dfs序+线段树
- matlab 数据是否符合正态分布的判断方法
- 基于ProtocolBuffer和ysocket的Swift即时通讯服务器搭建
- Linux 系统批量安装字体的方法
- tomcat7解压版安装过程
- MFC通过窗口标题获得窗口句柄
- opencv codebook背景减除
- 手机计算机数据消失了怎么恢复,手机数据丢失的恢复方法
- 算法之显著性检测《Saliency Detection: A Spectral Residual A》
- 领导和同事嫌弃你的6个征兆,离失业不远了
- 文本预处理库spaCy的基本使用(快速入门)
- VS2022+PCL 1.12.1
- 图说卡尔曼滤波(C++实现)
- python培训报告,简述Python语言经验总结_python知识点总结_python培训
- java模拟回合制游戏大小姐_[源码和文档分享]基于java的RPG回合制游戏
- AD16画PCB流程及集成库制作注意事项
- 硕士论文中期汇报ppt_华北理工大学附属唐山市人民医院硕士学位论文开题、中期汇报会圆满结束...
热门文章
- INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES错误解决方法
- variable java_在XSLT中使用Variable Argument调用Java方法
- 计算机组成原理考试知识点总结,最新2018计算机组成原理期末复习考试知识点复习考点归纳总结总结...
- 问题集锦(56-57)
- binostat matlab,MATLAB概率统计函数(2)
- java 互斥量_什么是Java中的互斥和信号量?主要区别是什么?
- intellij_使用IntelliJ ..已经2周了,到目前为止还算不错
- matlab 2009a使用教程,实验一 安装MATLAB R2009a软件及其简单操作
- android 8.0的imei简书,Android 8.0通知栏渠道,渠道组的适配和使用
- js java cookie_JS 打开一个模式窗口,使用Cookie传递一个参数