C++线程基础笔记(一)
标准写法:
#include<iostream>
#include<thread>
using namespace std;
void MyThread()
{
cout << "MyThread线程1开始了" << endl;
cout << ".................." << endl;
cout << "MyThread线程1结束了" << endl;
} int main()
{
thread my(MyThread);
my.join(); cout<<"主线程开始了"<< endl;
cout<<"............."<< endl;
cout<<"主线程结束了"<< endl; return 0;
}
输出结果:

分析:
首先利用可调用对象MyThread创建了子线程my;
然后调用类thread的函数join,表示只有当我的子线程结束了,主线程才可以结束;说白了它的作用就是用来堵塞主线程的.
如果不加join函数,那么主进程和子进程就会同时执行,不分先后,如果子线程还没结束主线程就结束了,那么系统会抛出异常,如下代码:
#include<iostream>
#include<thread>
using namespace std;
void MyThread()
{
cout << "MyThread线程1开始了" << endl;
cout << ".................." << endl;
cout << "MyThread线程1结束了" << endl;
} int main()
{
thread my(MyThread);
//my.join(); cout<<"主线程开始了"<< endl;
cout<<"............."<< endl;
cout<<"主线程结束了"<< endl; return 0;
}
输出:

如果我就想让主线程先退出,但是不抛出异常,那么可以用detach(),如下代码:
#include<iostream>
#include<thread>
using namespace std;
void MyThread()
{
cout << "MyThread线程1开始了" << endl;
cout << ".................." << endl;
cout << "MyThread线程1结束了" << endl;
} int main()
{
thread my(MyThread);
my.detach(); cout<<"主线程开始了"<< endl;
cout<<"............."<< endl;
cout<<"主线程结束了"<< endl; return 0;
}
输出:

对于使用detach(),存在许多隐患,比如:
#include<iostream>
#include<thread>
using namespace std;
class MyThread
{
public:
int &x;
MyThread(int &_x):x(_x) {}
void operator()()
{ cout << "子线程开始执行了" << endl;
cout << "x的值是:" << x << endl;
cout << "..............." << endl;
cout << "子线程结束了" << endl;
}
}; int main()
{
int data = 1;
MyThread myobj(data);
thread my(myobj);
my.detach(); cout<<"主线程开始了"<< endl;
cout<<"............."<< endl;
cout<<"主线程结束了"<< endl; return 0;
}
输出:

分析:
1.这里造成的原因主要就是因为我的类中含有引用,对于刚开始用int data=1生成的变量,main结束后(主线程结束),data就会消失,由于我使用了detach,所以主线程和子线程谁先谁后结束不确定,如果主线程先结束了,data也会跟着消失,子线程再去访问该数据便会无从寻起。
基于此,可能连带产生如下困惑,如下两行代码:
MyThread myobj(data);。。。。。。。。。。。。①
thread my(myobj); .。。。。。。。。。。。。。。②
如果主线程先结束,那么myobj对象一同消失,那么②的代码中的myobj不也会消失吗?
为了解答这个问题,做如下实验:
#include<iostream>
#include<thread>
using namespace std;
class MyThread
{
public:
int &x;
MyThread(int &_x):x(_x) {}
MyThread(const MyThread& another):x(another.x)
{ cout << "拷贝构造函数被执行" << endl;
}
~MyThread()
{
cout << "析构函数被执行" << endl;
}
void operator()()
{ cout << "子线程开始执行了" << endl;
cout << "x的值是:" << x << endl;
cout << "..............." << endl;
cout << "子线程结束了" << endl;
}
}; int main()
{
int data = 1;
MyThread myobj(data);
thread my(myobj);
my.detach(); cout<<"主线程开始了"<< endl;
cout<<"............."<< endl;
cout<<"主线程结束了"<< endl; return 0;
}
输出:

以上代码只有thread my(myobj); 这一句才有可能发生拷贝构造.
所以对于:
MyThread myobj(data);。。。。。。。。。。。。①
thread my(myobj); .。。。。。。。。。。。。。。②
①到②会发生拷贝构造,图的运行结果就是证明。
如果join或者detach其中一个已被使用,那么就不能再次被使用,
类库提供了一个joinable函数可以判断是否已被使用,看如下代码:
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.join(); 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。①
34 if (my.joinable())
35 {
36 cout << "join或者detach可以被使用" << endl;
37 }
38 else
39 {
40 cout << "join或者detach已经被用" << endl;
41 }
42 my.detach();。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。②
43 if (my.joinable())
44 {
45 cout << "join或者detach可以被使用" << endl;
46 }
47 else
48 {
49 cout << "join或者detach已经被用" << endl;
50 }
51 cout<<"主线程开始了"<< endl;
52 cout << "..............." << endl;
53 cout << "主线程结束了" << endl;
54
55 return 0;
56 }
对①和②插入断点进行调试:

第一次进入了if语句,继续调试:
当执行第二个时候发生了异常。
继续实验:

更加证实了前面的观点,join或者detach两者只能使用其中的一个,并且只能一次。
C++线程基础笔记(一)的更多相关文章
- 《CLR via C#》读书笔记 之 线程基础
第二十五章 线程基础 2014-06-28 25.1 Windows为什么要支持线程 25.2 线程开销 25.3 停止疯狂 25.6 CLR线程和Windows线程 25.7 使用专用线程执行异步的 ...
- CLR via C# 读书笔记-26.线程基础
前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...
- Python学习基础笔记(全)
换博客了,还是csdn好一些. Python学习基础笔记 1.Python学习-linux下Python3的安装 2.Python学习-数据类型.运算符.条件语句 3.Python学习-循环语句 4. ...
- C#面试题(转载) SQL Server 数据库基础笔记分享(下) SQL Server 数据库基础笔记分享(上) Asp.Net MVC4中的全局过滤器 C#语法——泛型的多种应用
C#面试题(转载) 原文地址:100道C#面试题(.net开发人员必备) https://blog.csdn.net/u013519551/article/details/51220841 1. . ...
- C#多线程编程系列(二)- 线程基础
目录 C#多线程编程系列(二)- 线程基础 1.1 简介 1.2 创建线程 1.3 暂停线程 1.4 线程等待 1.5 终止线程 1.6 检测线程状态 1.7 线程优先级 1.8 前台线程和后台线程 ...
- Jmeter使用基础笔记-写一个http请求
前言 本篇文章主要讲述2个部分: 搭建一个简单的测试环境 用Jmeter发送一个简单的http请求 搭建测试环境 编写flask代码(我参考了开源项目HttpRunner的测试服务器),将如下的代码保 ...
- C#线程学习笔记九:async & await入门二
一.异步方法返回类型 只能返回3种类型(void.Task和Task<T>). 1.1.void返回类型:调用方法执行异步方法,但又不需要做进一步的交互. class Program { ...
- Java基础笔记 – Annotation注解的介绍和使用 自定义注解
Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 | 被围观 25,969 views+ 1.Anno ...
- php代码审计基础笔记
出处: 九零SEC连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059 --------------------------- ...
随机推荐
- JAVA工具类获取HttpServletRequest、HttpServletResponse 对象
添加依赖 <!-- Spring Web --> <dependency> <groupId>org.springframework</groupId> ...
- c++11之find 和 find_if 和 find_if_not 用法
时刻提醒自己 Note: vector的释放 0.头文件 #include <algorithm> 1.区别 返回范围 [first, last) 中满足特定判别标准的首个元素: 函数 功 ...
- 【LeetCode】 204. Count Primes 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 素数筛法 参考资料 日期 [LeetCode] 题目 ...
- 【LeetCode】434. Number of Segments in a String 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 统计 正则表达式 字符串分割 日期 题目地址:htt ...
- LeetCode 1482. 制作 m 束花所需的最少天数
LeetCode 1482. 制作 m 束花所需的最少天数 题目 给你一个整数数组 bloomDay,以及两个整数 m 和 k . 现需要制作 m 束花.制作花束时,需要使用花园中 相邻的 k 朵花 ...
- C. Tourist's Notes
C. Tourist's Notes time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 1170 - Counting Perfect BST
1170 - Counting Perfect BST PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 3 ...
- TensorFlow.NET机器学习入门【8】采用GPU进行学习
随着网络越来约复杂,训练难度越来越大,有条件的可以采用GPU进行学习.本文介绍如何在GPU环境下使用TensorFlow.NET. TensorFlow.NET使用GPU非常的简单,代码不用做任何修改 ...
- 编写Java程序,创建一个父类交通工具类(Vehicles),以及两个子类,分别是轿车类(Car)和卡车类(Truck)。
返回本章节 返回作业目录 需求说明: 创建一个父类交通工具类(Vehicles),以及两个子类,分别是轿车类(Car)和卡车类(Truck). 父类有属性品牌(brand)和颜色(color). 在父 ...
- 编写Java程序,模拟五子棋博弈过程中的异常声明和异常抛出
返回本章节 返回作业目录 需求说明: 模拟五子棋博弈过程中的异常声明和异常抛出,判断用户所下棋子的位置,是否超越了棋盘的边界. 棋盘的横坐标的范围为0-9,纵坐标范围为0-14,如果用户所放棋子的坐标 ...