C++线程的简单学习及了解

news2024/9/23 9:35:39

此篇文章只是线程的简单了解。

文章目录

  • 前言
  • 一、线程的优缺点
  • 二、C++线程库
    • 1.thread类的简单介绍
    • 2.线程函数参数
  • 总结


前言

什么是线程?

在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”
一切进程至少都有一个执行线程
线程在进程内部运行,本质是在进程地址空间内运行
透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流

一、线程的优缺点

1.线程的优点:

创建一个新线程的代价要比创建一个新进程小得多
与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
线程占用的资源要比进程少很多
能充分利用多处理器的可并行数量
在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。
2.线程的缺点
性能损失:一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。
健壮性降低:编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造响。
编程难度提高:编写与调试一个多线程程序比单线程程序困难得多
3.线程异常
单个线程如果出现除零,野指针问题导致线程崩溃,进程也会随着崩溃。
线程是进程的执行分支,线程出异常,就类似进程出异常,进而触发信号机制,终止进程,进程终止,该进程内的所有线程也就随即退出。
4.线程用途
合理的使用多线程,能提高CPU密集型程序的执行效率。
合理的使用多线程,能提高IO密集型程序的用户体验(如生活中我们一边写代码一边下载开发工具,就是多线程运行的一种表现)。

二、C++线程库

1.thread类的简单介绍

C++11 之前,涉及到多线程问题,都是和平台相关的,比如 windows linux 下各有自己的接
口,这使得代码的可移植性比较差 C++11 中最重要的特性就是对线程进行支持了,使得 C++
并行编程时不需要依赖第三方库 ,而且在原子操作中还引入了原子类的概念。要使用标准库中的
线程,必须包含 < thread > 头文件。
以下是线程相关的函数:
函数名: thread()   功能:构造一个线程对象,没有关联任何线程函数,即没有启动任何线程
函数名:
thread(fn,
args1, args2,
...)     这里的...是可变参数列表,我会在后面深入学习线程的文章中详细介绍。   功能: 构造一个线程对象,并关联线程函数fnargs1args2...为线程函数的参数
函数名:get_id()     功能:获取线程id
函数名: jionable()   功能:线程是否还在执行,joinable代表的是一个正在执行中的线程。
函数名: jion()     功能:该函数调用后会阻塞住线程,当该线程结束后,主线程继续执行
函数名: detach()    功能:在创建线程对象后马上调用,用于把被创建线程与线程对象分离开,分离的线程变为后台线程,创建的线程的"死活"就与主线程无关
注意:
1. 线程是操作系统中的一个概念, 线程对象可以关联一个线程,用来控制线程以及获取线程的
状态
2. 当创建一个线程对象后,没有提供线程函数,该对象实际没有对应任何线程。如下图:
#include <thread>
#include <iostream>
using namespace std;
int main()
{
 std::thread t1;
 cout << t1.get_id() << endl;
 return 0;
}

 上图中get_id的返回值类型为id类型,id类型实际为std::thread命名空间下封装的一个类,该类中包含一个结构体,如下:

// vs下查看
typedef struct
{ /* thread identifier for Win32 */
 void *_Hnd; /* Win32 HANDLE */
 unsigned int _Id;
} _Thrd_imp_t;

3.当创建一个线程对象后,并且给线程关联线程函数,该线程就被启动,与主线程一起运行。 线程函数一般情况下可按照以下三种方式提供:  1.函数指针   2.lambda表达式   3.函数对象

以下为三种方式的代码:

#include <iostream>
using namespace std;
#include <thread>
void ThreadFunc(int a)
{
 cout << "Thread1" << a << endl;
}
class TF
{
public:
 void operator()()
 {
 cout << "Thread3" << endl;
 }
};
int main()
{
 // 线程函数为函数指针
 thread t1(ThreadFunc, 10); 
 // 线程函数为lambda表达式
 thread t2([]{cout << "Thread2" << endl; });
 // 线程函数为函数对象
 TF tf;
 thread t3(tf);
 t1.join();
 t2.join();
 t3.join();
 cout << "Main thread!" << endl;
 return 0;
}

4.thread类是防拷贝的,不允许拷贝构造以及赋值,但是可以移动构造和移动赋值,即将一个

线程对象关联线程的状态转移给其他线程对象,转移期间不意向线程的执行。
5.可以通过jionable()函数判断线程是否是有效的,如果是以下任意情况,则线程无效:
1.采用无参构造函数构造的线程对象。
2.线程对象的状态已经转移给其他线程对象
3.线程已经调用jion或者detach结束

2.线程函数参数

线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的 ,因此:即使线程参数为引用类型,在
线程中修改后也不能修改外部实参,因为 其实际引用的是线程栈中的拷贝,而不是外部实参
演示代码如下:
#include <thread>
void ThreadFunc1(int& x)
{
 x += 10;
}
void ThreadFunc2(int* x)
{
 *x += 10;
}
int main()
{
 int a = 10;
 // 在线程函数中对a修改,不会影响外部实参,因为:线程函数参数虽然是引用方式,但其实际
引用的是线程栈中的拷贝
 thread t1(ThreadFunc1, a);
 t1.join();
 cout << a << endl;
 // 如果想要通过形参改变外部实参时,必须借助std::ref()函数
 thread t2(ThreadFunc1, std::ref(a);
 t2.join();
 cout << a << endl;
 // 地址的拷贝
 thread t3(ThreadFunc2, &a);
 t3.join();
 cout << a << endl;
 return 0;
}
注意:如果是类成员函数作为线程参数时,必须将this作为线程函数参数。
以上就是线程的一小部分的简单学习,我们这篇文章的深度很浅很浅,就是给初学者看一看,对于更深入的c++11的所有新特性我会在后面的文章中详细并且深入的讲解。

总结

c++11新特性中的lambda和线程都是值得学习的,由于我现在对lambda和线程学习的很浅所以本篇文章只是讲了我目前所简单学到的一些知识,在后面的文章中我会详细的重新介绍lambda函数以及线程等c++11新特性的学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/464936.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git 使用大全及各种疑难杂症解决方法(长期更新)

Git使用中遇到的各种问题及解决方法 git clone后修改文件然后再上传覆盖 git push出现“Everything up-to-date”解决方法 git commit后如何撤销或修改 git 同步远程和本地的同名分支 git push异常问题出现符号解决方法 git 删除最近或者任意一次提交commit

Http详解

一、什么是Http协议 Http全称为超文本传输协议&#xff0c;是目前使用最主流的 应用层协议&#xff0c; 二、Http工作过程 当我们在浏览器中输入一个 “网址”, 此时浏览器就会给对应的服务器发送⼀个 HTTP 请求. 对方服务器收到这个请求之后, 经过计算处理, 就会返回⼀个 …

DAY06_常用API上

1&#xff1a;API 概述 1.1 API概述 如何自己设计对象并使用 获取已有对象并使用 而关于第一块知识&#xff1a;学习如何自己设计对象并使用&#xff0c;现在已经有一些基础了。 API(Application Programming Interface) &#xff1a;应用程序编程接口 那如何理解应用程序…

软件测试技术(四)白盒测试

白盒测试 白盒测试&#xff08;White Box Testing&#xff09;又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试只测试软件产品的内部结构和处理过程&#xff0c;而不测试软件产品的功能&#xff0c;用于纠正软件系统在描述、表示和规格上的错误&#xff0c…

IDEA弹出`Lombok requires enabled annotation processing`错误信息

问题背景 项目启动时&#xff0c;弹出一个报错窗口 问题原因 当您使用 Lombok 库时&#xff0c;您可能会遇到Lombok requires enabled annotation processing的错误消息。这是因为 Lombok 库使用了 Java 注解处理器&#xff08;annotation processor&#xff09;&#xff0c;而…

MySQL学习笔记第四天

第04章运算符 3.逻辑运算符 逻辑运算符主要用来判断表达式的真假&#xff0c;在MySQL中&#xff0c;逻辑运算符的返回结果为1、0或者NULL。 MySQL中支持4种逻辑运算符如下&#xff1a; 3.1逻辑非运算符 逻辑非&#xff08;NOT或!&#xff09;运算符表示当给定的值为0时返回…

【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务

限流器的算法选项 随着互联网的快速发展&#xff0c;越来越多的应用程序需要处理大量的请求。如果没有限制&#xff0c;这些请求可能会导致应用程序崩溃或变得不可用。因此&#xff0c;限流器是一种非常重要的技术&#xff0c;可以帮助应用程序控制请求的数量和速率&#xff0…

【JavaEE初阶】多线程(四)阻塞队列 定时器 线程池

文章目录 多线程案例阻塞队列概念生产者消费者模型标准库中的阻塞队列自己实现一个阻塞队列 定时器概念标准库中的定时器实现定时器 线程池标准库中的线程池工厂模式 ThreadPoolExecutor();构造方法参数详解(重点)实现线程池 多线程案例 阻塞队列 概念 阻塞队列是一种特殊的…

【软考备战·希赛网每日一练】2023年4月26日

文章目录 一、今日成绩二、错题总结第一题 三、知识查缺 题目及解析来源&#xff1a;2023年04月26日软件设计师每日一练 一、今日成绩 二、错题总结 第一题 解析&#xff1a; 数据耦合&#xff1a;一组模块借助参数表传递简单数据。 公共耦合&#xff1a;多个模块都访问同一个…

C++题解 | 逆波兰表达式相关

✨个人主页&#xff1a; 夜 默 &#x1f389;所属专栏&#xff1a; C/C相关题解 &#x1f38a;每篇一句&#xff1a; 图片来源 A year from now you may wish you had started today. 明年今日&#xff0c;你会希望此时此刻的自己已经开始行动了。 文章目录 &#x1f307;前言…

改进YOLOv8 | 即插即用篇 | YOLOv8 引入 RepVGG 重参数化模块 |《RepVGG:让VGG风格的卷积神经网络再次伟大》

我们提出了一种简单但功能强大的卷积神经网络结构,该模型在推理时类似于VGG,只有33的卷积和ReLU堆叠而成,而训练时间模型具有多分支拓扑结构。训练时间和推理时间结构的这种解耦是通过结构重新参数化技术实现的,因此该模型被命名为RepVGG。在ImageNet上,RepVGG达到了超过8…

手把手教你搭建属于自己的服务器

最近总是想搭建自己的网站&#xff0c;奈何皮夹里空空如也&#xff0c;服务器也租不起&#xff0c;更别说域名了。于是我就寻思能否自己搭建个服务器&#xff0c;还不要钱呢&#xff1f; 还真行&#xff01;&#xff01;&#xff01; 经过几天的冲浪&#xff0c;我发现有两个免…

AlgoC++第七课:手写Matrix

目录 手写Matrix前言1. 明确需求2. 基本实现2.1 创建矩阵2.2 外部访问2.3 <<操作符重载 3. 矩阵运算3.1 矩阵标量运算3.2 通用矩阵乘法3.3 矩阵求逆 4. 完整示例代码总结 手写Matrix 前言 手写AI推出的全新面向AI算法的C课程 Algo C&#xff0c;链接。记录下个人学习笔记…

01 背包 (二维 )

首先是我对背包问题的理解&#xff1a; 有一个背包可以放下 n kg&#xff0c;有一些物品&#xff0c;价值和重量一一对应&#xff0c;问题是&#xff0c;需要怎样才能使背包中的价值最大&#xff1f; 不同的规则对应不同的背包问题 01背包&#xff1a;每一个物品只能被放入一次…

Docker consul的容器集群的部署|consul-template部署

Docker consul的容器集群的部署|consul-template部署 一、Consul 概述基于nginx和consul构建高可用及自动发现的Docker服务架构 二 consul实验步骤2.1 部署Consul集群 (server)2.2 Consul部署&#xff08;Client端&#xff09;2.3 consul-template部署(server)2.4 编译安装ngin…

【翻译一下官方文档】邂逅uniCloud云函数(基础篇)

我将用图文的形式&#xff0c;把市面上优质的课程加以自己的理解&#xff0c;详细的把&#xff1a;创建一个uniCloud的应用&#xff0c;其中的每一步记录出来&#xff0c;方便大家写项目中&#xff0c;做到哪一步不会了&#xff0c;可以轻松翻看文章进行查阅。&#xff08;此文…

量表题如何分析?

量表是一种测量工具&#xff0c;量表设计标准有很多&#xff0c;并且每种量表的设计都有各自的特性&#xff0c;不同量表的特性也决定了测量尺度&#xff0c;在数据分析中常用的量表为李克特量表。李克特量表1932年由美国社会心理学家李克特在当时原有总加量表的基础上进行改进…

Java8使用Stream流实现List列表简单使用

目录 1.forEach() 2.filter&#xff08;T -> boolean&#xff09; 3.findAny()和findFirst() 4.map(T -> R) 和flatMap(T -> stream) 5.distinct() 去重 6.limit(long n)和skip(long n) 7.anyMatch(T -> boolean) 8.allMatch(T -> boolean) 9.noneMat…

ASP.NET Core MVC 从入门到精通之数据库

随着技术的发展&#xff0c;ASP.NET Core MVC也推出了好长时间&#xff0c;经过不断的版本更新迭代&#xff0c;已经越来越完善&#xff0c;本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容&#xff0c;适用于初学者&#xff0c;在校毕业生&#xff0c…

ThingsBoard教程(三四):筛选规则节点 根据资产,设备,筛选,asset profile switch,device profile switch

前言 这是规则节点解析系列的第一篇,让我们先从Filter Nodes ,筛选节点类型开始。 筛选节点的作用主要是为了从筛选进入规则链的数据,根据一定的判断表达式来判断,数据向下游的那个分支流转。类似我们编程中的switch语句或if语句。 本篇主要讲解asset profile switch 与de…