标准写法:

  1. #include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. void MyThread()
  5. {
  6. cout << "MyThread线程1开始了" << endl;
  7. cout << ".................." << endl;
  8. cout << "MyThread线程1结束了" << endl;
  9. }
  10.  
  11. int main()
  12. {
  13. thread my(MyThread);
  14. my.join();
  15.  
  16. cout<<"主线程开始了"<< endl;
  17. cout<<"............."<< endl;
  18. cout<<"主线程结束了"<< endl;
  19.  
  20. return 0;
  21. }

输出结果:

分析:

首先利用可调用对象MyThread创建了子线程my;

然后调用类thread的函数join,表示只有当我的子线程结束了,主线程才可以结束;说白了它的作用就是用来堵塞主线程的.

如果不加join函数,那么主进程和子进程就会同时执行,不分先后,如果子线程还没结束主线程就结束了,那么系统会抛出异常,如下代码:

  1. #include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. void MyThread()
  5. {
  6. cout << "MyThread线程1开始了" << endl;
  7. cout << ".................." << endl;
  8. cout << "MyThread线程1结束了" << endl;
  9. }
  10.  
  11. int main()
  12. {
  13. thread my(MyThread);
  14. //my.join();
  15.  
  16. cout<<"主线程开始了"<< endl;
  17. cout<<"............."<< endl;
  18. cout<<"主线程结束了"<< endl;
  19.  
  20. return 0;
  21. }

输出:

如果我就想让主线程先退出,但是不抛出异常,那么可以用detach(),如下代码:

  1. #include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. void MyThread()
  5. {
  6. cout << "MyThread线程1开始了" << endl;
  7. cout << ".................." << endl;
  8. cout << "MyThread线程1结束了" << endl;
  9. }
  10.  
  11. int main()
  12. {
  13. thread my(MyThread);
  14. my.detach();
  15.  
  16. cout<<"主线程开始了"<< endl;
  17. cout<<"............."<< endl;
  18. cout<<"主线程结束了"<< endl;
  19.  
  20. return 0;
  21. }

输出:

对于使用detach(),存在许多隐患,比如:

  1. #include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. class MyThread
  5. {
  6. public:
  7. int &x;
  8. MyThread(int &_x):x(_x) {}
  9. void operator()()
  10. {
  11.  
  12. cout << "子线程开始执行了" << endl;
  13. cout << "x的值是:" << x << endl;
  14. cout << "..............." << endl;
  15. cout << "子线程结束了" << endl;
  16. }
  17. };
  18.  
  19. int main()
  20. {
  21. int data = 1;
  1. MyThread myobj(data);
  2. thread my(myobj);
  3. my.detach();
  4.  
  5. cout<<"主线程开始了"<< endl;
  6. cout<<"............."<< endl;
  7. cout<<"主线程结束了"<< endl;
  8.  
  9. return 0;
  10. }

输出:

分析:

1.这里造成的原因主要就是因为我的类中含有引用,对于刚开始用int data=1生成的变量,main结束后(主线程结束),data就会消失,由于我使用了detach,所以主线程和子线程谁先谁后结束不确定,如果主线程先结束了,data也会跟着消失,子线程再去访问该数据便会无从寻起。

基于此,可能连带产生如下困惑,如下两行代码:

MyThread myobj(data);。。。。。。。。。。。。①
thread my(myobj); .。。。。。。。。。。。。。。②

如果主线程先结束,那么myobj对象一同消失,那么②的代码中的myobj不也会消失吗?

为了解答这个问题,做如下实验:

  1. #include<iostream>
  2. #include<thread>
  3. using namespace std;
  4. class MyThread
  5. {
  6. public:
  7. int &x;
  8. MyThread(int &_x):x(_x) {}
  9. MyThread(const MyThread& another):x(another.x)
  10. {
  11.  
  12. cout << "拷贝构造函数被执行" << endl;
  13. }
  14. ~MyThread()
  15. {
  16. cout << "析构函数被执行" << endl;
  17. }
  18. void operator()()
  19. {
  20.  
  21. cout << "子线程开始执行了" << endl;
  22. cout << "x的值是:" << x << endl;
  23. cout << "..............." << endl;
  24. cout << "子线程结束了" << endl;
  25. }
  26. };
  27.  
  28. int main()
  29. {
  30. int data = 1;
  31. MyThread myobj(data);
  32. thread my(myobj);
  33. my.detach();
  34.  
  35. cout<<"主线程开始了"<< endl;
  36. cout<<"............."<< endl;
  37. cout<<"主线程结束了"<< endl;
  38.  
  39. return 0;
  40. }

输出:

以上代码只有thread my(myobj); 这一句才有可能发生拷贝构造.

所以对于:

MyThread myobj(data);。。。。。。。。。。。。①
thread my(myobj); .。。。。。。。。。。。。。。②

①到②会发生拷贝构造,图的运行结果就是证明。

如果join或者detach其中一个已被使用,那么就不能再次被使用,

类库提供了一个joinable函数可以判断是否已被使用,看如下代码:

  1. 1 #include<iostream>
  2. 2 #include<thread>
  3. 3 using namespace std;
  4. 4 class MyThread
  5. 5 {
  6. 6 public:
  7. 7 int &x;
  8. 8 MyThread(int &_x):x(_x) {}
  9. 9 MyThread(const MyThread& another):x(another.x)
  10. 10 {
  11. 11
  12. 12 cout << "拷贝构造函数被执行" << endl;
  13. 13 }
  14. 14 ~MyThread()
  15. 15 {
  16. 16 cout << "析构函数被执行" << endl;
  17. 17 }
  18. 18 void operator()()
  19. 19 {
  20. 20
  21. 21 cout << "子线程开始执行了" << endl;
  22. 22 cout << "x的值是:" << x << endl;
  23. 23 cout << "..............." << endl;
  24. 24 cout << "子线程结束了" << endl;
  25. 25 }
  26. 26 };
  27. 27
  28. 28 int main()
  29. 29 {
  30. 30 int data = 1;
  31. 31 MyThread myobj(data);
  32. 32 thread my(myobj);
  33. 33 my.join(); 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。①
  34. 34 if (my.joinable())
  35. 35 {
  36. 36 cout << "join或者detach可以被使用" << endl;
  37. 37 }
  38. 38 else
  39. 39 {
  40. 40 cout << "join或者detach已经被用" << endl;
  41. 41 }
  42. 42 my.detach();。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。②
  43. 43 if (my.joinable())
  44. 44 {
  45. 45 cout << "join或者detach可以被使用" << endl;
  46. 46 }
  47. 47 else
  48. 48 {
  49. 49 cout << "join或者detach已经被用" << endl;
  50. 50 }
  51. 51 cout<<"主线程开始了"<< endl;
  52. 52 cout << "..............." << endl;
  53. 53 cout << "主线程结束了" << endl;
  54. 54
  55. 55 return 0;
  56. 56 }

对①和②插入断点进行调试:

第一次进入了if语句,继续调试:

当执行第二个时候发生了异常。

继续实验:

更加证实了前面的观点,join或者detach两者只能使用其中的一个,并且只能一次。

C++线程基础笔记(一)的更多相关文章

  1. 《CLR via C#》读书笔记 之 线程基础

    第二十五章 线程基础 2014-06-28 25.1 Windows为什么要支持线程 25.2 线程开销 25.3 停止疯狂 25.6 CLR线程和Windows线程 25.7 使用专用线程执行异步的 ...

  2. CLR via C# 读书笔记-26.线程基础

    前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...

  3. Python学习基础笔记(全)

    换博客了,还是csdn好一些. Python学习基础笔记 1.Python学习-linux下Python3的安装 2.Python学习-数据类型.运算符.条件语句 3.Python学习-循环语句 4. ...

  4. C#面试题(转载) SQL Server 数据库基础笔记分享(下) SQL Server 数据库基础笔记分享(上) Asp.Net MVC4中的全局过滤器 C#语法——泛型的多种应用

    C#面试题(转载) 原文地址:100道C#面试题(.net开发人员必备)  https://blog.csdn.net/u013519551/article/details/51220841 1. . ...

  5. C#多线程编程系列(二)- 线程基础

    目录 C#多线程编程系列(二)- 线程基础 1.1 简介 1.2 创建线程 1.3 暂停线程 1.4 线程等待 1.5 终止线程 1.6 检测线程状态 1.7 线程优先级 1.8 前台线程和后台线程 ...

  6. Jmeter使用基础笔记-写一个http请求

    前言 本篇文章主要讲述2个部分: 搭建一个简单的测试环境 用Jmeter发送一个简单的http请求 搭建测试环境 编写flask代码(我参考了开源项目HttpRunner的测试服务器),将如下的代码保 ...

  7. C#线程学习笔记九:async & await入门二

    一.异步方法返回类型 只能返回3种类型(void.Task和Task<T>). 1.1.void返回类型:调用方法执行异步方法,但又不需要做进一步的交互. class Program { ...

  8. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  9. php代码审计基础笔记

    出处: 九零SEC连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059 --------------------------- ...

随机推荐

  1. 使用proxy解决请求跨域问题

    背景 在 react 项目里,前端请求接口时出现了跨域问题(类似图片中的提示) 这时最快捷的方法就是让后端同学设置请求允许跨域(如图配置响应头) 如果后端同学不配合,就需要靠我们自己来了! 实现 Re ...

  2. MyBatis中比较(大于、小于)符号的转义写法

    <     < <=   <= >    > >=   >= &     & '     &apos; "     & ...

  3. 【LeetCode】961. N-Repeated Element in Size 2N Array 解题报告(Python & C+++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典 日期 题目地址:https://leetcod ...

  4. 【LeetCode】930. Binary Subarrays With Sum 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 二分查找 字典 相似题目 参考资料 日期 题目地址: ...

  5. 【LeetCode】80. Remove Duplicates from Sorted Array II 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  6. 【LeetCode】494. Target Sum 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址:https://leetc ...

  7. Windows11实现录屏直播,H5页面直播 HLS ,不依赖Flash

    这两天的一个小需求,需要实现桌面实时直播,前面讲了两种方式: 1.Windows 11实现录屏直播,搭建Nginx的rtmp服务 的方式需要依赖与Flash插件,使用场景有限 2.Windows 11 ...

  8. CS5211完全替代兼容LT7211|PS8625|CH7511方案|EDP转LVDS|Capstone CS5211

    CH7511|LT7211|PS8625替代方案--Capstone CS5211AN 设计EDP转LVDS优势方案原理图+PCB板设计 CH7511|LT7211|PS8625这三款都是专门用于设计 ...

  9. 生成对抗网络GAN与DCGAN的理解

    作者在进行GAN学习中遇到的问题汇总到下方,并进行解读讲解,下面提到的题目是李宏毅老师机器学习课程的作业6(GAN) 一.GAN 网络上有关GAN和DCGAN的讲解已经很多,在这里不再加以赘述,放几个 ...

  10. Spring企业级程序设计 • 【第6章 深入Spring MVC开发】

    全部章节   >>>> 本章目录 6.1 模型数据解析及控制器返回值 6.1.1 ModelAndView多种用法 6.1.2  Map添加模型数据和返回String类型值 6 ...