C++线程创建的方式和使用

news2024/11/18 16:32:24

进程与线程

  • 进程
    简单的可以认为是一个程序执行的过程。进程就是活跃的程序,在内存中运行,占用系统的资源。
  • 线程
    线程也叫轻量级进程,通常一个进程包含若干个线程。线程可以利用进程所拥有的资源。在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,比如我们在利用微信聊天的同时,也可以和别人文字聊天。

并发

两个或者多个独立的活动同时进行的现象称为并发。并发可以简单的认为,可以理解成多个应用程序同时运行。在单核CPU中,并发实际上是一种假象,进程之间实际上是按照一定的分配算法轮流使用CPU。
并发的实现主要有两种方式:
1.多进程实现并发
2.单个进程,多个线程实现并发,就是一个主线程多个子线实现。

C++中创建线程的方式

  • 头文件 #include
  • 创建线程:调用 thread 类去调用一个线程的对象
#include<iostream>
#include<thread>
using namespace std;
void print(){
	cout<<"子线程在运行。。。"<<endl;
}
int main(){
	//创建线程
	thread t1(print);//print为线程处理函数
	cout<<"主线程。。。"<<endl;
	return 0;
}

运行结果:
在这里插入图片描述
可以看到,主线程和子线程的运行顺序是不一样的,在其他的编译器中,可能不会出现“子线程在运行。。。”的语句。

join( )函数

可以利用 join 函数加入,汇合线程,阻塞主线程。添加以后等线程运行结束之后才运行主线程。注意 一个线程只能join一次,不能重复。

#include<iostream>
#include<thread>
#include<windows.h>
using namespace std;
//线程处理函数
void print(){
	Sleep(2000);//休眠2s
	cout<<"子线程在运行..."<<endl;
}
int main(){
	//创建线程
	thread t1(print);
	t1.join();//阻塞 ,添加以后等线程运行结束之后才运行主线程
	cout<<"主线程..."<<endl;
	return 0;
}
//运行结果:
/*
子线程在运行。。。
主线程。。。
*/

detach( )函数

detach( ) 函数用于打破主线程和子线程之间的依赖关系,将子线程和主线程之间进行分离,不影响。
detach后,就不能再join

void print(){
	Sleep(2000);//休眠2s
	cout<<"子线程在运行..."<<endl;
}
int main(){
	//创建线程
	thread t1(print);
	t1.detach();//子线程与主线程分离
	cout<<"主线程..."<<endl;
	return 0;
}
//运行结果:
/*
主线程...
*/

joinable( )函数

joinable( ) 函数是一个布尔类型的函数,他会返回一个布尔值来表示当前的线程是否是可执行线程(能被join或者detach),因为相同的线程不能join两次,也不能join完再detach,同理也不能detach,所以joinable函数就是用来判断当前这个线程是否可以joinable的。

#include<iostream>
#include<thread>
using namespace std;
void print(){
	cout<<"子线程在运行。。。"<<endl;
}
int main(){
	thread t1(print);
	t1.join();
	cout<<"主线程..."<<endl;
	if(t1.joinable())
		cout<<"能join"<<endl;
	else
		cout<<"不能进行join"<<endl;
	return 0;
}
//运行结果
/*
子线程在运行。。。
主线程...
不能进行join
*/

创建线程的方式

创建线程的方式根据线程处理函数的不同,一共可以分成6种。

1.不带参的方式创建线程

不带参数的普通函数作为线程处理函数。

#include<iostream>
#include<thread>
using namespace std;
void print(){
	cout<<"子线程在运行。。。"<<endl;
}
int main(){
	//创建线程
	thread t1(print);//print为线程处理函数
	cout<<"主线程。。。"<<endl;
	return 0;
}
/*
子线程在运行。。。
主线程。。。
*/

2.通过类和对象创建线程

利用类中的仿函数作为线程处理函数。

#include<iostream>
#include<thread>
using namespace std;
class A{
	//STL 仿函数 类名模仿函数的行为
	void operator()(){
		cout<<"子线程..."<<endl;
	}
};
int main(){
	//正常写法1  对象充当线程处理函数
	A a;
	thread t1(a);
	t1.join();
	
	//写法2
//	thread t1((A()));
//	t1.join();
	
	cout<<"主线程..."<<endl;
}

3.通过Lambda表达式创建线程

Lambda表达式简单地说,就是将函数定义和调用放在一处实现。

#include<iostream>
#include<thread>
using namespace std;
int main(){
	thread  t1([]{cout<<"子线程调用..."<<endl;});
	t1.join();
	cout<<"主线程..."<<endl;
}
//运行结果
/*
子线程调用...
主线程...
*/

4.带参的方式创建线程

将带参数的函数作为线程处理函数。

#include<iostream>
#include<thread>
using namespace std;
void p1(int &n){
	cout<<"子线程"<<n<<endl;
	n++;
}
int main(){
	int n=0;
	thread t3(p1,std::ref(n));//ref用于包装引用传值
	t3.join();
	thread t31(p1,std::ref(n));
	t31.join();
	cout<<"主线程..."<<endl;
}
/*
子线程0
子线程1
主线程...
*/

5.智能指针的方式创建线程

就是以智能指针为参数的函数作为线程处理函数

void p2(unique_ptr<int> ptr){
	cout<<"子线程:"<<ptr.get()<<endl;
	cout<<"子线程id: "<<this_thread::get_id()<<endl;//get_id函数获取线程id
}

int main(){
	//智能指针为参数的线程处理函数
	int *p=new int(12);
	cout<<*p<<endl;//12
	unique_ptr<int> ptr(new int(1000));
	cout<<"主线程:"<<ptr.get()<<endl;//ptr.get() 获取智能指针的地址
	thread t4(p2,move(ptr));
	t4.join();
	cout<<"主线程id: "<<this_thread::get_id()<<endl;
	cout<<"主线程..."<<ptr.get()<<endl;//0000000 因为上面的语句将智能指针移动到p3中去,子线程结束后,智能指针自动释放啦。
}
/*
12
主线程:0x2b630bb1760
子线程:0x2b630bb1760
子线程id: 2
主线程id: 1
主线程...000000000
*/

6.类的成员函数创建线程

将类的成员函数作为线程处理函数

class B{
public:
	void p3(int &num){
		num=1100;
		cout<<"子线程id:"<<this_thread::get_id()<<endl;
	}
};
int main(){
	//类的成员函数充当线程处理函数
	B b;
	int num=10;
	//需要告诉是哪一个对象的成员函数
	thread t5(&B::p3,b,ref(num));//注意创建thread类对象的方式
	t5.join();
	cout<<"主线程id: "<<this_thread::get_id()<<endl;
}
/*
子线程id:2
主线程id: 1
*/

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

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

相关文章

关于软件文档写作

关于软件文档写作目录概述需求&#xff1a;设计思路实现思路分析1.业务逻辑2.代码表达3.形式归纳4.方式和工具参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better resul…

JS模块化—CJSAMDCMDES6-前端面试知识点查漏补缺

本文从以时间为轴从以下几个方面进行总结JS模块化。从无模块化 > IIFE > CJS > AMD > CMD > ES6 > webpack这几个阶段进行分析。 历史 幼年期&#xff1a;无模块化 方式 需要在页面中加载不同的js&#xff0c;用于动画&#xff0c;组件&#xff0c;格式化…

【软件测试】一个边界值事故,领导leader心里苦季度奖金没了还被罚3K......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 项目组长&#xff1…

java类的练习--下面给出一个根据雇员类型利用多态性完成

java类的练习–下面给出一个根据雇员类型利用多态性完成… 题目 ​ 下面给出一个根据雇员类型利用多态性完成工资单计算的程序。定义一个类Employee作为超类&#xff0c;Employee的子类有Boss&#xff08;每星期发给他固定工资&#xff0c;而不计工作时间&#xff09;、Piece…

顶级“Redis学习笔记”,缓存雪崩+击穿+穿透+集群+分布式锁,NB了

如果你是一位后端工程师&#xff0c;面试时八成会被问到 Redis&#xff0c;特别是那些大型互联网公司&#xff0c;不仅要求面试者能简单使用 Redis&#xff0c;还要深入理解其底层实现原理&#xff0c;具备解决常见问题的能力。可以说&#xff0c;熟练使用 Redis 就是后端工程师…

超140支爆款B站恰饭,2022年B站双11战报来了!

- 导语 从0到3.06亿月活&#xff0c;从“与世无争”到今天手持高粘性、高活跃的用户参战双十一&#xff0c;在B站的品牌们有了更成熟的营销模式。 2022年双十一已经落下帷幕&#xff0c;在B站全面拥抱双十一的火热氛围下&#xff0c;有哪些品牌做到了声量、销量双丰收&#x…

【毕业设计】深度学习人脸表情识别系统 - python

文章目录0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码4 最后0 前言 &#x1f525; Hi&#xff0c;大家好&#xff0c;这里是丹成学长的毕设系列文章&#xff01; &#x1f5…

基于 BERT 实现的情感分析(文本分类)----概念与应用

文章目录基于 BERT 的情感分析(文本分类)基本概念理解简便的编码方式: One-Hot 编码突破: Word2Vec编码方式新的开始: Attention 与 Transformer 模型四方来降: 超一流预处理模型 BERT 诞生BERT 实现情感分析数据预处理并创建数据集定义网络模型定义训练函数与评估函数设置损失…

AVL树的插入(C++实现)

1. 概念 AVL树&#xff08;Adelson-Velsky and Landis Tree&#xff09;于1962年被提出&#xff0c;是计算机科学中最早被发明的平衡二叉查找树。AVL树得名于它的发明者G. M. Adelson-Velsky和Evgenii Landis。 在AVL树中&#xff0c;任一节点对应的两棵子树的最大高度差为1&…

大一新生HTML期末作业 个人网页王嘉尔明星介绍网页设计与制作

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

领悟《信号与系统》之 信号与系统的描述-上节

信号与系统的描述-上节一、信号分类1. 一维信号和多维信号2. 确定信号和随机信号3. 连续时间信号和离散时间信号4. 周期信号和非周期信号5. 能量信号和功率信号二、常见工程信号1. 正弦信号2. 指数信号3. 取样信号4. 单位矩形脉冲信号5. 符号函数在真实的物理世界中&#xff0c…

Redis的优惠券秒杀问题(五)全局唯一ID 以及 秒杀下单

Redis的优惠券秒杀问题&#xff08;五&#xff09;全局唯一ID 以及 秒杀下单 关于优惠秒杀问题的Redis实现章节总览 全局唯一ID 场景分析 不能用自增的原因 id的规律性太明显 受单表数据量的限制 全局唯一ID的条件 全局唯一ID的Redis实现 代码实现 单元测试 其它…

【FPGA】FPGA实现SPI协议读写FLASH(一)----- M25P16操作概述

文章目录一、FLASH介绍&#xff08;M25P16&#xff09;1、M25P16概述2、SPI模式3、存储结构4、指令集5、时间参数二、M25P16工作原理三、M25P16指令操作1、页编程 (PP)2、扇区擦除和整块擦除 (SE and BE)3、写使能 (WREN)4、读ID&#xff08;RDID&#xff09;5、读状态寄存器&a…

使用c#将aj-report桌面化:1.winform嵌入浏览器

说到底,aj-report是个工具,我想大多数人还是想快速使用它来创建一个可以展示的工具。通过之前的章节,你应该可以制作自己的报表页面了,下面我们来看看怎么把aj-report包装成一个桌面能够运行的软件。 当然作为扩展开发,受开源协议限制,我们不能大规模修改aj-report的源代…

【毕业设计】深度学习图像修复算法研究与实现 - python

文章目录1 前言2 什么是图像内容填充修复3 原理分析3.1 第一步&#xff1a;将图像理解为一个概率分布的样本3.2 补全图像3.3 快速生成假图像3.4 生成对抗网络(Generative Adversarial Net, GAN) 的架构3.5 使用G(z)生成伪图像4 在Tensorflow上构建DCGANs5 最后1 前言 &#x1…

PC_OS中断/中断屏蔽字

文章目录程序中断&#x1f383;中断概念中断功能(作用)中断请求中断源中断分类外中断非屏蔽中断和可屏蔽中断陷入(内中断)硬件中断和软件中断关系整理&#x1f388;中断判优&#x1f388;中断优先级CPU响应中断的条件外中断实现思路&#x1f388;中断隐指令 及其工作①关中断②…

下一个倒下的是不是Genesis

今日&#xff0c;一个关于“Genesis今晚破产”的传言在各个社交平台传播&#xff0c;包括行业的KOL也在讨论这个事情&#xff0c;认为Genesis或存在偿付能力问题&#xff0c;该公司将于美国东部时间11月17日8&#xff1a;00am与债权人通话以解释情况。若消息属实&#xff0c;Ge…

【AGC】flutter之agconnect_crash在ios上崩溃

问题背景 flutter agconnect_crash-1.2.0300 运行在ios平台上&#xff0c;出现了如下这个崩溃 NSInvalidArgumentException: *** [NSJSONSerialization dataWithJSONObject:options:error:]: value parameter is nil 0 CoreFoundation 0x00000001830d005c 0x183037000 62678…

视频讲解vue2基础之渲染v-if/v-show/v-for/v-html

大家好&#xff0c;我是你们的老朋友lqj_本人&#xff0c;最近一周没有更新文章了&#xff0c;是因为最近学校有一些活动比赛&#xff0c;也有一部分原因就是我在录制一些关于前端方面的视频&#xff0c;涉及到的领域主要一前端&#xff0c;比如&#xff1a;H5开发&#xff0c;…

项目经理如何搞懂难缠的客户【静说】

作为乙方的项目经理&#xff0c;是否经常遇见难缠的客户&#xff0c;现环境下&#xff0c;大部分都是甲方强势&#xff0c;乙方弱势&#xff0c;双方处于一种不对等的基础上&#xff0c;项目经理如何生产&#xff0c;成功交付项目呢&#xff1f; 流程机制上如何应对&#xff1…