C++多线程1(复习向笔记)

创建线程以及相关函数

当用thread类创建线程对象绑定函数后,该线程在主线程执行时就已经自动开始执行了,join起到阻塞主线程的作用

#include <iostream>
#include <thread>
#include <string>
using namespace std;
//测试函数
void printString(string str)
{
	cout << str << endl;
}
int main()
{
	//创建线程,需要包括thread头文件,构造函数后续参数里可选,放入线程绑定函数的参数
	thread thread1(printString,"Hello World!");
	//joinable函数,有些线程不一定能用join或者detach,joinable返回一个布尔值,true时使用join增加严谨性
	bool flag = thread1.joinable();
	if (flag)
		thread1.join();//主程序等待线程执行完毕,不加join可能会导致线程绑定的函数没执行完,主程序就结束了

	//分离主线程和子线程,会可能导致子线程还未执行完毕,主线程就结束了
	/*thread1.detach();*/
	return 0;
}

使用detach输出结果,一般使用较少
在这里插入图片描述
更直观的join和joinable的例子

#include <iostream>
#include <thread>
using namespace std;

void display()
{
	for (int i = 0; i < 100; i++)
		cout << i << " ";
	cout << endl << "子线程结束" << endl;
}

int main()
{
	thread thread1(display);
	bool flag = thread1.joinable();

	if (flag)
		thread1.join();
	cout << "主线程结束" << endl;
	return 0;
}

输出
不难发现,主线程阻塞在了join中,等待子线程执行完毕,再往下执行

常见问题以及解决方法

一般注意变量的声明周期即可

绑定函数的参数为引用

使用ref()函数

#include <iostream>
#include <thread>
using namespace std;

void test01(int& a)
{
	a += 1;
}
int main()
{
	int a = 11;
	//绑定函数时参数,传递引用时需要用std下的ref函数将变量转换为引用类型,否则thread无法判断为引用类型
	thread thread1(test01, ref(a));
	if (thread1.joinable())
		thread1.join();
	cout << a << endl;
	return 0;
}

在这里插入图片描述
错误例子,运行结果报错,也有可能不报错
错误原因,在本例中,a不在main中,函数执行完后内存会释放掉,由于是线程模式,test01和test02的执行速度不一致,有可能在test02执行完后,test01还没有执行完,所以导致了空指针异常!
解决方法:将a变成局部变量

#include <iostream>
#include <thread>
using namespace std;
thread thread1;
void test01(int& a)
{
	a += 1;
}

void test02()
{
	int a = 11;
	//绑定函数时参数,传递引用时需要用std下的ref函数将变量转换为引用类型,否则thread无法判断为引用类型
	thread1 = thread(test01, ref(a));
}
int main()
{
	
	test02();
	if (thread1.joinable())
		thread1.join();
	return 0;
}

指针提前释放

//指针案例
void test03(int* a)
{
	cout << "*a = " << * a << endl;
}
int main()
{
	int* p = new int(1);
	thread thread1(test03,p);
	//在join之前手动释放了指针,指针指向的空间值变成了随机值
	delete p;
	if (thread1.joinable())
		thread1.join();
	return 0;
}

在这里插入图片描述

类成员函数作为线程函数,但对象被提前释放

其实跟指针的报错差不多,注意在join()之前不要释放对象即可
智能指针可以减少在join()之前手动释放的问题,它会自动调用析构函数自己销毁对象
整体源代码

#include <iostream>
#include <thread>
#include <memory>
using namespace std;
//引用案例
void test01(int& a)
{
	a += 1;
}
//指针案例
void test03(int* a)
{
	cout << "*a = " << * a << endl;
}
//类案例
class A {
public:
	void func()
	{
		cout << "类成员函数作为线程函数" << endl;
	}
};
int main()
{
	A a;
	//类成员函数作为线程函数时,需要用&来制定成员函数的地址,同时还需要传递指针/引用
	thread thread1(&A::func,&a);
	thread1.join();
	//智能指针,已经是指针了
	shared_ptr<A> b = make_shared<A>();
	//直接传入值即可
	thread thread2(&A::func, b);
	thread2.join();
	return 0;
}

在这里插入图片描述

互斥锁解决变量访问互质问题

学过OS这部分就很容易理解了
只是C++具体实现罢了,具体看代码
线程安全:如果多线程程序每一次运行的结果跟单线程程序运行的结果是一样的,那么就称这个线程是安全的

#include <iostream>
#include <thread>
#include<mutex>
using namespace std;
mutex mtx;
int a = 0;
void add()
{
	for (int i = 0; i < 1000; i++)
	{
		//上锁相当于P(mutex)
		mtx.lock();
		a++;
		//解锁相当于V(mutex)
		mtx.unlock();
	}
		
}
int main()
{
	//创建两个线程
	thread thread1(add);
	thread thread2(add);

	thread1.join();
	thread2.join();
	//输出共享变量
	cout << a << endl;
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java强训day10(选择题编程题)

选择题 public class Test01 {public static void main(String[] args) {try{int i 100 / 0;System.out.print(i);}catch(Exception e){System.out.print(1);throw new RuntimeException();}finally{System.out.print(2);}System.out.print(3);} }编程题 题目1 import jav…

day 59 503.下一个更大元素II 42. 接雨水

vector的扩充要熟悉 vector<int> numsT(nums.begin(),nums.end()); nums.insert(nums.end(),numsT.begin(),numsT.end()); class Solution { public:vector<int> nextGreaterElements(vector<int>& nums) {stack<int> st;vector<int> nums…

C++入门(一)— 使用VScode开发简介

文章目录 C 介绍C 擅长领域C 程序是如何开发编译器、链接器和库编译预处理编译阶段汇编阶段链接阶段 安装集成开发环境 &#xff08;IDE&#xff09;配置编译器&#xff1a;构建配置配置编译器&#xff1a;编译器扩展配置编译器&#xff1a;警告和错误级别配置编译器&#xff1…

自动驾驶代客泊车AVP决策规划详细设计

背景 随着产品的不断迭代&#xff0c;外部停车场的铺开&#xff0c;PAVP车辆需要应对的场景将越来越复杂&#xff0c;因此整体算法泛化能力的提升显得尤为关键。为了打磨巡航规划的能力&#xff0c;算法架构应当设计的更为灵活&#xff0c;可以针对使用场景迁入更为先进有效的算…

Springboot 快速集成 ES

1、Springboot 官网给出的版本选择标准 2、选择版本依赖 我的 elasticsearch 服务版本为 7.17.13&#xff0c;所以 springboot 版本我选用 2.7.10 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies<…

电脑上如何压缩图片?这个方法简单又方便

电脑上如何压缩图片&#xff1f;我们在需要压缩图片大小的时候&#xff0c;最经常使用的就是下载安装一些图片处理软件&#xff0c;这样的方法不仅耽误时间&#xff0c;有些软件的操作步骤还特别繁琐&#xff0c;对新手小白非常不友好&#xff0c;所以小编今天就给大家介绍一个…

巴厘行记(四)——乌布漫游

欢迎览阅《巴厘行记》系列文章 巴厘行记巴厘行记&#xff08;一&#xff09;——海神庙 巴厘行记&#xff08;二&#xff09;——乌布之夜 巴厘行记&#xff08;三&#xff09;——Auntie和Mudi 巴厘行记&#xff08;四&#xff09;——乌布漫游 巴厘行记&#xff08;五&a…

Spring MVC 基本知识

知识回顾 Tomcat 是 Servlet 容器&#xff0c;会解析 Java Web 应用下的 WEB-INF/web.xml 文件&#xff0c;得到相关的 Servlet 组件。 原理解析 Spring MVC 实际是定义了一个 DispatcherSevlet 来统一管理当前 Web 应用下的 Path 路径。在 DispatchSevlet 中持有了一个 Spr…

Mybatis-plus原生pages分页未生效的解决方案

文章目录 前言原因1、Mybatis Plus版本的问题2、Mapper.xml文件中SQL语句格式问题3、Mybatis Plus默认分页拦截器问题4、分页参数传参问题5、分页配置的问题 解决方案1、升级对应的Mybatis-plus版本分页插件配置问题3、自定义分页拦截器4、正确的参数5、不同版本的配置文件3.4.…

笨蛋总结JVM

笨蛋总结JVM 由于Java语言将自己的内存控制权交给了虚拟机&#xff0c;所以需要了解虚拟机的运行机制 &#xff08;主要用于回顾JVM&#xff09; 笨蛋总结JVM 笨蛋总结JVM1.运行时数据区域线程私有区域程序计数器Java虚拟机栈本地方法栈 线程共享区域堆方法区 1.2程序计数器…

Jmeter学习系列之二:工具面板必知必会

目录 前言 一、菜单栏 二、功能区 ​编辑 2.读入数据 总结 前言 Jmeter面板一共分为4个区域&#xff0c;分别是菜单栏、功能区、视图区和内容区。 菜单栏&#xff1a;主要功能包括新建测计划&#xff0c;添加线程组、测试脚本&#xff0c;分布式运行相关&#xff0c;查看…

腾讯云4核16G服务器价格,用于幻兽帕鲁Palworld专用

腾讯云幻兽帕鲁服务器4核16G、8核32G和16核64G配置可选&#xff0c;4核16G14M带宽66元一个月、277元3个月&#xff0c;8核32G22M配置115元1个月、345元3个月&#xff0c;16核64G35M配置580元年1个月、1740元3个月、6960元一年&#xff0c;腾讯云百科txybk.com分享腾讯云幻兽帕鲁…

基于JAVA+SpringBoot+Vue的前后端分离的美食分享推荐平台2

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 在当今社会&#xff0…

专注力训练+番茄工作法,拯救工作学习的效率

文章目录 1.丢失的专注力1.1.谁偷走了我的专注力1.2.是时候夺回我的专注力了 2.番茄工作法2.1.历史2.2.使用方式2.3.一些问题和思考 3.总结 1.丢失的专注力 不知道大家有没有遇到过一些无法专注的情况&#xff0c;在学习和工作的时候总是在被各种各样的事情打断&#xff0c;简…

使用WAF防御网络上的隐蔽威胁之反序列化攻击

​ 什么是反序列化 反序列化是将数据结构或对象状态从某种格式转换回对象的过程。这种格式通常是二进制流或者字符串&#xff08;如JSON、XML&#xff09;&#xff0c;它是对象序列化&#xff08;即对象转换为可存储或可传输格式&#xff09;的逆过程。 反序列化的安全风险 反…

机器学习算法实战案例:使用 Transformer 模型进行时间序列预测实战(升级版)

时间序列预测是一个经久不衰的主题&#xff0c;受自然语言处理领域的成功启发&#xff0c;transformer模型也在时间序列预测有了很大的发展。 本文可以作为学习使用Transformer 模型的时间序列预测的一个起点。 文章目录 机器学习算法实战案例系列答疑&技术交流数据集数据…

Kotlin快速入门系列7

Kotlin的数据类、密封类、枚举类 数据类 与Java等语言不同&#xff0c;kotlin创建只包含数据的类时&#xff0c;需要在类名前声明关键字&#xff1a;data。 data class KotlinBean (val brand : String) 在kotlin中&#xff0c;编译器会自动的从主构造函数中根据所有声明的…

[C++]c++判断CPU的类型及支持的指令集

1、利用cpui判断cpu的类型及支持的指令集&#xff0c;可以进行条件编程&#xff1a;&#xff08;InstructionSet.h&#xff09; #pragma once// InstructionSet.cpp // Compile by using: cl /EHsc /W4 InstructionSet.cpp // processor: x86, x64 // Uses the __cpuid intrin…

Node.js-express

1.了解Ajax 1.1 什么是ajax Ajax的全称是Asynchronous Javascript And XML&#xff08;异步Js和XML&#xff09;. 通俗的理解&#xff1a;在网页中利用XMLHttpRequest对象和服务器进行数据交互的方式&#xff0c;就是Ajax 1.2 为什么要学习Ajax 之前所学的技术&#xff0c…

单例模式-C#实现

该实例基于WPF实现&#xff0c;直接上代码&#xff0c;下面为三层架构的代码。 一 Model using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 设计模式练习.Model.单例模式 {//单例模式的实现in…