一、其他构造线程的方法

c++线程,除了可以利用普通函数创建线程外,还有其他创建线程的方法:

  • 类对象
  • Lambda表达式

具体使用方法如下:

#include <thread>using namespace std;class TA
{
public:void operator ()(){printf("%s", "线程开始执行 \n");}
};void main()
{TA ta;// thread 方法会调用TA的拷贝构造函数,所以使用detach方法,只要TA对象里没有引用和指针,就不会产生问题thread mThreadObj(ta);if (mThreadObj.joinable())mThreadObj.join();auto mLambdaThreaadObj = []{printf("%s", "线程开始执行 \n");};thread m_LambdaThread(mLambdaThreaadObj);if (m_LambdaThread.joinable())m_LambdaThread.join();
}

补充内容:
thread 方法会调用TA的拷贝构造函数,所以使用detach方法,只要TA对象里没有引用和指针,就不会产生问题,否则一旦传入主线程中的临时变量,并且主线程先于子线程执行完毕(可能会发生这种情况),那么程序运行情况就不可知,这是一定要避免的。

二、使用detach的隐患

首先,观察如下案例:

void mPrint(const int& i, char* pmBuff)
{printf("i : %d, buff: %s \n", i, pmBuff);
}void main()
{int mI = 1;int& mIy = mI;char mBuff[]= "this is a test";thread mThread(mPrint,mI, mBuff);mThread.join();
}

在mThread线程中,我传入了两个局部变量,并且接收函数中有两个参数,一个是引用类型,一个是指针类型。

如果我将线程的控制由join变为detach会引发什么问题?

很容易想到的是,因为主线程和子线程的结束时间不可控,所以局部变量的销毁时间不可控,那程序的运行情况就是未知的。再细究,这里由两个参数,是两个参数都会受影响,还是其中一个,又可能是哪一个?

因此,我将两者地址都进行了比较:

可以看到,引用类型的参数内存地址和主线程中不一样,指针类型的参数和主线程中的一样。因此可以得到结论,如果线程中的形参是引用类型,那主线程会将传入的值做一次赋值,所以不是真的直接引用绑定,但是如果形参是指针类型,那就不会拷贝

但如何避免这种情况呢?

我起初的思路是,只要再参数传递过程中,产生了拷贝那就是安全的(并不正确),因此我总结了c++中会调用拷贝构造函数的三种情形:

这里适用的就是第二种情况。

但是,我又反应过来,这个拷贝构造函数发生的时间是在主线程之前还是之后呢?如果是在主线程结束之后才调用,那detach的风险并没有规避掉,因此我又做了如下尝试:

#include <thread>using namespace std;class TA
{
public:int m_i;TA(const int& i) :m_i(i){printf("%s", "拷贝构造函数执行 \n");};void operator ()(){printf("%s", "线程开始执行 \n");}
};void mPrint( char* pmBuff,const TA&ta)
{printf("i : %d, buff: %s \n",ta.m_i, pmBuff);
}void main()
{int mI = 1;int& mIy = mI;char mBuff[]= "this is a test";//利用类型转化构造函数将整型转成TA类型thread mThread(mPrint, mBuff,mI);mThread.detach();
}

因为thread肯定会调用传入对象的拷贝构造函数,所以如果输出中没有显示拷贝构造函数的执行,那么就说明,拷贝可能发生在主线程结束之后。
执行结果:

结论:
这样也是不安全的。

那究竟如何解决detach的这个隐患呢?

通过翻阅资料发现,只需使用临时对象即可完美规避这个问题。
如下所示:

 thread mThread(mPrint, mBuff,TA(mI));

三、结论

1、如果传递简单类型参数,使用值传递,不要使用引用传递,杜绝使用指针传递;
2、如果传递类对象,在创建线程时就构造临时对象,在函数参数里,使用引用来接 。

(建议一律使用join,能避免90%的问题)

以上就是本篇文章的全部内容,如果不足,请批评指正。

本文转载自:深入理解c++多线程:(一)detach使用隐患

参考文章:C++ thread detach的大坑

c++多线程中detach的使用隐患相关推荐

  1. (单例设计模式中)懒汉式与饿汉式在多线程中的不同

    /*目的:分析一下单例设计模式中,懒汉式与饿汉式在多线程中的不同!开发时我们一般选择饿汉式,因为它简单明了,多线程中不会出现安全问题!而饿汉式需要我们自己处理程序中存在的安全隐患,但是饿汉式的程序技术 ...

  2. 【Linux】多线程中使用fork()

    (最核心的东西我在下面用红色字体标出来了,理解了那块,这些东西都是就理解了!) 在本篇文章开始之前,需要大家先了解线程和进程,这位大哥讲的言简意赅:进程和线程的主要区别(总结)_kuangsongha ...

  3. java闭合数据_java多线程中线程封闭详解

    线程封闭的概念 访问共享变量时,通常要使用同步,所以避免使用同步的方法就是减少共享数据的使用,这种技术就是线程封闭. 实现线程封闭的方法 1:ad-hoc线程封闭 这是完全靠实现者控制的线程封闭,他的 ...

  4. java多线程中的join方法详解

    java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...

  5. 了解多线程中的yield

    2019独角兽企业重金招聘Python工程师标准>>> 最近在学习多线程这一块,发现里面有好多让人产生误区的地方,今天我来分析下java多线程中的yield功能,希望其他朋友也可以从 ...

  6. 解决DataGridView在多线程中无法显示滚动条的问题

    解决DataGridView在多线程中无法显示滚动条的问题 参考文章: (1)解决DataGridView在多线程中无法显示滚动条的问题 (2)https://www.cnblogs.com/roph ...

  7. VMware 虚拟化编程(8) — 多线程中的 VixDiskLib

    目录 目录 前文列表 多线程注意事项 多线程中的 VixDiskLib 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDiskLib/VADP 概念简析 VMware 虚拟化 ...

  8. 如何在多线程中调用winform窗体控件2——实例篇

    如何在多线程中调用winform窗体控件2--实例篇 针对之前文章<如何在多线程中调用winform窗体控件>,下面举个我项目中的实际案例,这是一个我自定义控件在异步设置焦点时的代码.在新 ...

  9. android串口补位,Rust多线程中的消息传递机制

    代码说话. use std::thread; use std::sync::mpsc; use std::time::Duration; fn main() { let (tx, rx) = mpsc ...

  10. JAVA多线程中join()方法的详细分析

    虽然关于讨论线程join()方法的博客已经非常极其特别多了,但是前几天我有一个困惑却没有能够得到详细解释,就是当系统中正在运行多个线程时,join()到底是暂停了哪些线程,大部分博客给的例子看起来都像 ...

最新文章

  1. 【好文共分享】关于ora-04065和ora-04068的原理解释
  2. 【会议记录】第二次例会(10.06)记录
  3. Ajax — 第六天
  4. php省城联动_thinkPHP实现的省市区三级联动功能示例
  5. 第一范式转化为第二范式_深度解读《中国智能经济发展白皮书》:AI为核心驱动力,百度给出智能范式...
  6. 接口”安全机制”的设计
  7. Linux忘记密码修改密码
  8. 【ARM汇编】ARM 指令集和Thumb 指令集
  9. 微积分:2.2泰勒公式函数极值定积分
  10. MongoDB 6 安装 基本操作
  11. 三星Galaxy S10可能把加密货币推向数百万名精通高兴技术的手机用户
  12. 计算机专业的在职考研,2019年深造北京航空航天大学在职研究生计算机专业在职考研科目是什么...
  13. 职业规划:45岁之后,外企精英们去哪里?
  14. 《SAP HANA平台应用开发》—第2章2.1节熟悉HANA开发环境
  15. (进制转换)—— 十六进制转换
  16. MSYS2 瘦身小攻略
  17. 【解决方法】Appium 报错 Original error: chrome not reachable
  18. 前端 圆形进度图_使用CSS3实现圆形进度条
  19. 计算机视觉近10年发展回顾与未来发展方向
  20. 交直流与电路分析三板斧

热门文章

  1. python时间如何处理_python 时间处理
  2. 南极沉船_世界上一些神秘的沉船,都成了仿佛被世界遗弃的盛景
  3. python判断回文字符串不考虑空格符号大小写_检查带有忽略的标点符号、空格和cas的回文文本...
  4. dlp型3d打印机_创想三维一台3d打印机是多少钱
  5. php 三大魔术方法,PHP魔术方法
  6. php 数组 utf8,PHP数组编码gbk与utf8互相转换的两种方法实例分享
  7. pivot sqlserver 条件_SqlServer行转列(PIVOT),列转行(UNPIVOT)总结
  8. java multibox_月光软件站 - 编程文档 - Java - Struts 中 Multibox 的用法
  9. Springboot属性配置绑定
  10. 抗锯齿_《战地V》深度学习抗锯齿性能测试:对它最友好的竟然是4K