C++多线程编程(1):线程的创建方式

news2024/11/17 16:27:31

文章首发于我的个人博客:欢迎大佬们来逛逛

文章目录

  • 进行与线程
  • C++中如何实现多线程
  • 创建线程的多种方式
    • 无参函数
    • lambda表达式
    • 常成员函数
    • not常成员引用函数
    • 智能指针
    • 仿函数
    • 类的普通成员函数
    • 综合测试

进行与线程

多线程是指多个线程并发执行的过程。

进程与线程的关系:

  • 进程是一个独立运行的应用程序
  • 线程是指进程内独立执行的一个单元,一个进程中可能有多个线程。

C++中如何实现多线程

使用 #include <thread> 头文件,里面定义了很多的线程函数。

其中,使用 thread 创建一个线程.

比如我有两个函数,分别是:

  • print1是主线程。
  • 下面四个函数分别是子线程。
void print1() {
	std::cout << "主线程\n";
}
void printtttt1() {
	Sleep(2000);
	std::cout << "子线程1\n";
}
void printtttt2() {
	Sleep(2000);
	std::cout << "子线程2\n";
}
void printtttt3() {
	Sleep(2000);
	std::cout << "子线程3\n";
}

现在我们想让他们四个同时执行?如何操作。

  1. 首先来创建线程对象:

thread 用作线程对象类型,然后传递一个函数指针(以模板形式)给到这个对象,则这个对象就是一个线程对象

我们将这三个子线程分别为三个不同的线程对象。print1为主线程。

std::thread t1(printtttt1);
std::thread t2(printtttt2);
std::thread t3(printtttt3);

创建完成后我们使用 join将子线程添加到主线程中:

t1.join(); 
t2.join();
t3.join();

然后运行,就会发现,三个子线程和主线程同时结束,说明多线程有效。

int main() {
	std::thread t1(printtttt1);
	std::thread t2(printtttt2);
	std::thread t3(printtttt3);
	//t.join(); //子线程加入主线程
	//detach: 子线程和主线程各自玩个的,等待主线程执行完毕
	t1.join(); 
	t2.join();
	t3.join();
	print1();
	return 0;
}

观察到细节:

  • 三个子线程都有一个等待两秒的功能,如果不是多线程,则很容易想到单纯的运行这四个函数可能需要6秒多才完成
  • 但是他们四个是同时完成的,即只用了两秒
  • 并且我们没有限制线程之间的执行顺序,因此他们的顺序是任意的。

在这里插入图片描述


join函数就是将子线程加入到主线程,然后和主线程一起执行完毕。

还有个 detach函数:

  • detach: 子线程和主线程各玩各的的,等待主线程执行完毕则停止。
t1.detach();
t2.detach();
t3.detach();
print1();

则会出现什么?

  • 程序立刻结束,我管你子线程执行了没有,只要我的主线程结束了,则程序就结束。 因此程序直接执行主线程函数,而不会执行三个子线程。

在这里插入图片描述


joinable:对线程是否可以join和detach操作进行判断。即一个线程只能进行一次join或者detach操作,如果你写了很多的代码,明明已经join过一次了,但是忘记了,因此又join了一次,这时就会 报错!!!

该函数在可以 join 或 detach 的时候返回true,否则返回false。

因此常见的可以避免错误的方式:

if (t1.joinable()) {
		t1.join(); //t1.detach()
	}

创建线程的多种方式

thread类型的构造函数是怎样的呢? 它可以构造什么样的线程函数对象呢?

template <class _Fn, class... _Args,   .......... >
explicit thread(_Fn&& _Fx, _Args&&... _Ax) {
        _Start(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...);
}
  • Fn:接受一个函数指针。
  • Args:接受函数的参数。

无参函数

这是最简单的创建线程的方式:

// 1. 传递无参void函数
void print() {
	std::cout << "子线程: " << "传递无参void函数\n";
}
void create1() {
	std::thread t1(print);
	t1.join(); //加入主线程
}

lambda表达式

// 2. 传递lambda表达式
void create2() {
	std::thread t1([]() {
		std::cout << "lambda表达式\n";
		});

	if (t1.joinable()) {
		t1.join();
	}
}

常成员函数

  • 普通内置类型:int
  • 常引用:const string& ; const int&
  • 常指针:const int*
  • 都可以直接传递
// 3. 传递有参函数
// 3.1  普通参数
void print2(int num, const std::string& name, const int age, const int& yina, const int* cp) {
	std::cout << "num: " << num << " name: " << name << " age: " << age << " yina: "
		<< yina << " cp: " << *cp << '\n';
}
void create3() {
	int num = 10, age = 20, yina = 999, cpnum = 50;
	std::thread t1(print2, num, "你好", age, yina, &cpnum);
	if (t1.joinable()) {
		t1.join();
	}
}

not常成员引用函数

  • not常引用: 如果是**不带const**的引用类型,则必须使用 std::ref 修饰,否则会报错:
  • not常指针:不会报错。
// 必须加以 ref 修饰;否则就传递const的引用
void print3(int& num) {
	std::cout << "引用 num: " << num << '\n';
}
void create4() {
	int num = 10;
	std::thread t1(print3, std::ref(num));
	if (t1.joinable()) {
		t1.join();
	}
}

//不会报错,const和非const的指针都不会报错,传递地址即可
void print4(int* num) {
	std::cout << "指针 num: " << *num << '\n';
}
void create5() {
	int num = 10;
	std::thread t1(print4, &num);
	if (t1.joinable()) {
		t1.join();
	}
}

智能指针

传递智能指针 unique_ptr 需要加 move移动,因为unique_ptr只允许存在一份,但是移动后本地将消失。

void print5(std::unique_ptr<int> ptr) {
	std::cout << "智能指针: " << *ptr.get() << '\n';
}
void create6() {
	std::unique_ptr<int> pointer(new int{ 100 });
	std::thread t1(print5, std::move(pointer));
	if (t1.joinable()) {
		t1.join();
	}

	//null
	std::cout << "移动之后,智能指针: " << pointer.get() << '\n';
}

仿函数

直接传递即可。

class Foo {
public:
	Foo() {}
	void operator()() {
		std::cout << "仿函数\n";
	}
};
void create7() {
	Foo f = Foo();
	//1. 仿函数对象
	std::thread t1(f);
	if (t1.joinable()) {
		t1.join();
	}

	//2. 匿名函数对象
	std::thread t2((Foo()));
	if (t2.joinable()) {
		t2.join();
	}
}

类的普通成员函数

函数指针的形式,先传递类名所对应的**函数地址,然后再传递类对象**。

class Aoo {
public:
	Aoo() {}
	void test() {
		std::cout << "普通成员函数\n";
	}
};
void create8() {
	Aoo a = Aoo();
	std::thread t1(&Aoo::test,a);
	if (t1.joinable()) {
		t1.join();
	}
}

综合测试

int main() {
	create1();
	create2();
	create3();
	create4();
	create5();
	create6();
	create7();
	create8();
	return 0;
}

在这里插入图片描述


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

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

相关文章

WIFI版本云音响设置教程腾讯云平台版本

文章目录 WIFI版本云音响设置教程腾讯云平台版本一、申请设备三元素1.腾讯云物联网平台2.创建产品3.设置产品参数4.添加设备5.获取三元素 二、设置设备三元素1.打开MQTTConfigTools2.计算MQTT参数3.使用windows电脑的WIFI连接到设备热点4.设置参数 三、腾讯云物联网套件协议使用…

Linux基础全整理 从入门到放弃,一些想说的话

阅读目录 断更后一些想说的话用户useraddpasswdpasswd文件详解 chageusermoduserdelshadow 文件格式切换用户 用户组groupaddgroup文件格式groupmodgroupdel登陆远程机器 磁盘RAIDraid0&#xff08;安装系统&#xff09;raid1&#xff08;存放数据&#xff09;raid 5&#xff0…

盘点54个Python实用工具源码Python爱好者不容错过

盘点54个Python实用工具源码Python爱好者不容错过 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1OXyEh-Yy3JI90jvn6d6wRw?pwd8888 提取码&#xff1a;8888 项目名称 7z辅助破解工…

基于冠状病毒群体免疫算法优化概率神经网络PNN的分类预测 - 附代码

基于冠状病毒群体免疫算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于冠状病毒群体免疫算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于冠状病毒群体免疫优化的PNN网络5.测试结果6.参考文献7.Matlab代码 …

漂亮的pyqt6皮肤 PyOneDark_Qt_Widgets_Modern_GUIPublic

大家先看看界面图&#xff0c;真的很漂亮&#xff1a; github地址&#xff1a;GitHub - Wanderson-Magalhaes/PyOneDark_Qt_Widgets_Modern_GUI 作者还录了教程&#xff1a; TUTORIALS: Tutorial 01: https://youtu.be/QQGlTGYCMg0 Tutorial 02: https://youtu.be/LwKre2proDk…

Halcon (4):如何开始自学

文章目录 文章专栏前言Halcon文档Halcon基础案例文档英语阅读建议 结论 文章专栏 Halcon开发 前言 在我完成上一篇代码&#xff0c;halcon基础窗口事件写完了之后&#xff0c;我已经基本掌握了如何写一个简单的halcon程序。后面我学习新的知识的时候感觉遇到了瓶颈。因为网上没…

【C++】:模板进阶

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关C模板进阶的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

『亚马逊云科技产品测评』活动征文|借助AWS EC2搭建服务器群组运维系统Zabbix+spug

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道。 本文基于以下软硬件工具&#xff1a; aws ec2 frp-0.52.3 zabbix 6…

Web之JavaScript(jQuery)笔记

Web之HTML、CSS、JavaScript 三、JavaScriptJS调试变量自定义函数数据类型及转换运算符优先级内置函数数组事件DOM(Document Object Model 文档对象模型)jQuery Web之HTML笔记 Web之CSS笔记 三、JavaScript JavaScript&#xff08;简称“JS”&#xff09;是一种轻量级的面向对…

心怀祖国放眼世界 爱国人士华国中应邀参加美国旧金山2023(APEC)峰会

据相关媒体美国旧金山报道:2023亚太经合组织&#xff08;APEC&#xff09;领导人非正式会议将于11月15日至17日在美国旧金山召开。11月11日&#xff0c;本年度APEC高级财政官员和部长会晤在旧金山率先启动&#xff0c;APEC CEO峰会将于11月14日至16日开幕。著名爱国人士、亚太一…

《向量数据库指南》——亚马逊云科技向量数据库揭秘:点亮数据未来!

在我们讨论亚马逊云科技向量数据库之前,我们必须先搞懂向量数据库。 那么,向量数据库是什么呢?简单来说,向量数据库就是一种专门用于处理和查询向量数据的数据库。与传统数据库以表格形式组织和存储数据不同,向量数据库采用多维数值数组的形式处理和存储数据。它的主要目标…

和解电话(匿名电话)/情侣拉黑联系电话/虚拟号/虚拟中间号/拉黑联系项目代码

和解电话&#xff0c;又名匿名电话 使用中间号转接到被叫人&#xff0c;不显示呼叫人号码&#xff0c;类似美团隐私号 呼叫人A->中间号B->被叫人C 演示地址&#xff1a;微信打开(http://sms.test.4php.top/sms/phone) 实现代码如下 <section class"section&q…

图像分类(四) 全面解读复现GoogleNet_InceptionV1-V4

论文解读 InceptionV1 前言 论文题目: Going Deeper with Convolutions Googlenet论文原文地址:https://arxiv.org/pdf/1409.4842.pdf 之前看过VGG的论文&#xff08;VGG精读直达&#xff09;。当时VGG获得了 2014 ILSVRC 图像分类的第二名&#xff0c;今天来看一下第一名…

【linux网络】解读FTP文件传输服务器配置,揭秘百度云下载限速原理

目录 一、FTP文件传输协议 1.1FTP工作原理 1.2两种模式介绍 1.3FTP状态码 1.4FTP的三种用户分类 二、vsftpd软件的介绍 2.1服务端介绍 2.2不同操作系统下的客户端登录操作 三、vsftpd的常见配置 3.1修改默认的命令端口 3.2限制匿名用户登录&#xff08;系统原本是默…

鸿蒙:实现两个Page页面跳转

效果展示 这篇博文在《鸿蒙&#xff1a;从0到“Hello Harmony”》基础上实现两个Page页面跳转 1.构建第一个页面 第一个页面就是“Hello Harmony”&#xff0c;把文件名和显示内容都改一下&#xff0c;改成“FirstPage”&#xff0c;再添加一个“Next”按钮。 Entry Compone…

[每周一更]-(第73期):介绍容器监控工具-CAdvisor

CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行CAdvisor用户可以轻松的获取到当前主机上容器的运行统计信息&#xff0c;并以图表的形式向用户展示。 命令行监控Docker容器-docker stats 访问地址 http://localhost:8080/containers/ …

ADS村田电感.mod(spice netlist文件)和.s2p模型导入与区别

ADS村田电感.mod&#xff08;spice netlist文件&#xff09;和.s2p模型导入与区别 简介环境过程s2pspice netlist&#xff08;.mod文件&#xff09;导入和结果对比 简介 记录了ADS村田电感.mod&#xff08;spice netlist文件&#xff09;和.s2p模型导入与区别 环境 ADS2020 …

安顿APP3.0全新升级,引领智能穿戴健康革新,专注预警疾病风险

随着人们生活水平的提高和工作压力的增加&#xff0c;心脑血管疾病已经成为现代社会的严重问题&#xff0c;特别是心梗、脑卒中等疾病已经开始夺去年轻人的生命。 据报道&#xff0c;近年来&#xff0c;多位年轻人因心脑血管疾病突发去世&#xff0c;如42岁的知名男演员、30岁的…

基于猕猴Spike运动解码的不同解码方法性能对比

公开数据集中文版详细描述 参考前文&#xff1a;https://editor.csdn.net/md/?not_checkout1&spm1011.2124.3001.6192神经元Spike信号分析 参考前文&#xff1a;https://blog.csdn.net/qq_43811536/article/details/134359566?spm1001.2014.3001.5501神经元运动调制分析 …

【MATLAB源码-第83期】基于matlab的MIMO中V-BALST结构ZF和MMSE检测算法性能误码率对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 在多输入多输出&#xff08;MIMO&#xff09;通信系统中&#xff0c;V-BLAST&#xff08;垂直波束形成层间空间时间编码技术&#xff09;是一种流行的技术&#xff0c;用于提高无线通信的数据传输速率和容量。它通过在不同的…