2.C++多线程--危险点分析

news2024/11/24 12:49:11

1.detach使用时分析


使用detach时,子线程一定不要传入指针


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

void my_print(const int& num1,const char* str) {
	cout << num1 << " " << str << endl;
}
//主进程结束后,才开始对子进程中的值进行拷贝。但是主进程释放了str1,子进程接收时会出现问题。
int main() {
	int num1 = 1;
	char str1[] = "hello,world!";
	thread obj1(my_print,num1,str1);
	obj1.detach();
	cout << "主进程结束运行" << endl;
	return 0;
}

如果采用临时类对象作为参数,传入到thread中,thread会调用拷贝构造函数,对传入变量进行拷贝,然后再为自线程所使用。

下面的代码采用引用来接收类对象,如果不采用引用的话,系统还会再构造一次对象,这样会出现3次构造,浪费时间。


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

class son_thread {
public:
	int m_a;
	son_thread(int a):m_a(a) {
		cout << "构造函数的调用" << endl;
	}
	~son_thread() {
		cout << "析构函数的调用" << endl;
	}
};

void my_print(const int a,const son_thread& st) {
	cout << a << " " << st.m_a << endl;
}
int main() {
	int num1 = 1;
	int num2 = 10;
	thread obj1(my_print, num1,son_thread(num2));
	obj1.detach();
	cout << "主进程结束运行" << endl;
	return 0;
}

2. 临时对象


1.如果对象采用隐式转换,将会在子线程中进行构造对象;

2.如果对象采用显示转换,将会在主线程中进行构造对象,并会调用拷贝构造函数。

this_thread::get_id()---->显示线程的id号

注意:

当采用隐式传递时,是在子线程进行类对象构造,但是此时主线程已经销毁,主线程内的局部变量已经释放,此时操作会有危险。

当采用显式构造是,首先会在主线程构造出一个临时对象,然后在主线程中进行复制拷贝构造,随后在主线程内将临时对象进行释放。


#include<iostream>
#include<thread>
using namespace std;
class son_thread {
public:
	int m_a;
	son_thread(int a) :m_a(a) {
		cout << "son_thread构造函数调用" << this_thread::get_id() << endl;
	}
	son_thread(const son_thread& base):m_a(base.m_a) {
		cout << "son_thread拷贝构造函数的调用" << this_thread::get_id()<< endl;
	}
	~son_thread() {
		cout << "son_thread析构函数调用" << this_thread::get_id()<< endl;
	}
};
void my_print(const son_thread& base) {
	cout << base.m_a << " my_print调用" << this_thread::get_id()<< endl;
}
int main() {
	int temp_a = 1;
	cout << "主线程的id:" << this_thread::get_id() << endl;
	//thread obj1(my_print, temp_a);
	thread obj1(my_print, son_thread(temp_a));
	obj1.join();
	cout << "主线程调用完毕:" << this_thread::get_id() << endl;

	return 0;
}

 3.传递智能指针、类对象


因为在传递类对象是,子线程会调用拷贝构造函数,因此子线程修改类对象成员变量时,并不会修改主线程内的对象成员变量。

此时我们可以用:std::ref()函数

在传入unique_ptr智能指针时,可以使用std::move()对智能指针进行更改。


#include<iostream>
#include<thread>
using namespace std;
class son_thread {
public:
	int m_a;
	son_thread(int a) :m_a(a) {
		cout << "son_thread构造函数调用" << this_thread::get_id() << endl;
	}
	son_thread(const son_thread& base) :m_a(base.m_a) {
		cout << "son_thread拷贝构造函数的调用" << this_thread::get_id() << endl;
	}
	~son_thread() {
		cout << "son_thread析构函数调用" << this_thread::get_id() << endl;
	}
};
void my_print(unique_ptr<int>temp_pt) {
	cout << *temp_pt << " my_print调用" << this_thread::get_id() << endl;
}
int main() {
	int temp_a = 1;
	cout << "主线程的id:" << this_thread::get_id() << endl;
	unique_ptr<int>u_pt(new int (100));
	thread obj1(my_print, std::move(u_pt));
	obj1.join();
	cout << "主线程调用完毕:" << this_thread::get_id() << endl;

	return 0;
}

4.将类函数的函数作为入口函数 


  


#include<iostream>
#include<thread>

using namespace std;
class son_thread {
public:
	int m_a;
	son_thread(int a) :m_a(a) {
		cout << "son_thread构造函数调用" << this_thread::get_id() << endl;
	}
	son_thread(const son_thread& base) :m_a(base.m_a) {
		cout << "son_thread拷贝构造函数的调用" << this_thread::get_id() << endl;
	}
	~son_thread() {
		cout << "son_thread析构函数调用" << this_thread::get_id() << endl;
	}
	void my_print(const int a ) {
		cout << a << " 类内函数的调用" << endl;
	}
};

int main() {
	cout << "主线程的id:" << this_thread::get_id() << endl;
	son_thread s1(10);
	thread obj1(&son_thread::my_print, s1, 100);
	obj1.join();
	cout << "主线程调用完毕:" << this_thread::get_id() << endl;
	return 0;
}

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

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

相关文章

MySQL 事务处理语言 TCL

文章目录 事务处理语言 TCL事务简介事务控制并发事务的隔离挑战脏读不可重复读幻读 事务的隔离级别未提交读&#xff08;READ-UNCOMMITED&#xff09;提交读&#xff08;READ COMMITED&#xff09;可重复读&#xff08;REPEATABLE READ&#xff09;可串行化&#xff08;SERIALI…

虹科案例 | 筒仓液位测量可以这么简单?

Part.01 行业挑战 在料箱、料斗或筒仓中使用散装物料的制造商需要准确可靠的液位检测来管理和处理库存&#xff0c;并最大限度地减少生产延迟。 塑料成型、食品加工和建筑材料等行业都依赖于散装材料。随着这些行业越来越接近准时制&#xff08;JIT&#xff09;制造&#xff…

认识协议【网络基础】

文章目录 什么是协议结构化数据结构化数据非结构化数据半结构化数据 结构化数据的传输序列化和反序列化 网络版计算器概述制定协议通过字符串传输结构化数据序列化与反序列化 实现计算器网络相关接口框架服务端客户端 制定协议请求响应发送和接收数据 计算逻辑测试存在的问题 T…

修改数组【并查集】

这里写自定义目录标题 并查集并查集的表示方法 题目输入描述输入示例输出示例 解题思路参考连接 并查集 并查集就是对集合的合并和查询操作的统称。他要求参与运算的两个集合是不相交的(不含有相同的元素)。针对这两个集合可以进行的操作&#xff1a; 1.合并&#xff1a;将两个…

复习之Linux系统中的进程管理

1.什么是进程&#xff1f;线程&#xff1f; 进程&#xff08;Process&#xff09;&#xff1a;是操作系统进行资源分配的最小单位。一个进程是一个程序的一次执行过程。每启动一个进程&#xff0c;操作系统就会为它分配一块独立的内存空间&#xff0c;用于存储PCB、数据段、程…

如何从复盘中获得真正的收获?持续改进是关键!

复盘&#xff0c;本是围棋术语&#xff0c;每次博弈结束后&#xff0c;双方棋手把刚才的对局复演一遍&#xff0c;分析对局当中得失关键&#xff0c;提升自己棋力的好方法。复盘是对思维的训练。 通过复盘&#xff0c;当类似局面再次出现&#xff0c;你就能快速预测接下来的动态…

【网络】TCP套接字创建服务客户端与守护进程

文章目录 Tcp服务端TcpServer.hppTcpServer.cc Tcp客户端TcpClient.hppTcpClient.cc TCP客户端处理守护进程守护进程化 Tcp服务端 TcpServer.hpp TCP服务端创建流程如下&#xff1a; 创建socket文件套接字对象&#xff0c;面向字节流SOCK_STREAM bind绑定自己的网络信息&…

nacos注册中心配置springboot动态刷新源码解读

0丶简介 如何快速启动,请去官网看文档,言简意赅 https://nacos.io/zh-cn/docs/quick-start.html 只描述为何实现动态刷新的关键源码 1丶基于目前最新版本 <!-- https://mvnrepository.com/artifact/com.alibaba.boot/nacos-config-spring-boot-starter --> <depend…

命名管道详解

一、命名管道 1、命名管道与匿名管道一个很显著的区别是&#xff1a;匿名管道只能在有血缘关系的进程间进行通信&#xff0c;但命名管道可以让两个毫无关系的进程进行通信。 2、如果我们想在不相关的进程间交换数据&#xff0c;我们可以用到FIFO文件来进行通信&#xff0c;这…

【Nginx rewrite】

目录 一、常见的Nginx 正则表达式二、location1、location 解释2、location 示例说明&#xff1a;3、实际网站使用中&#xff0c;至少有三个匹配规则定义&#xff1a; 二、rewrite1、rewrite跳转实现&#xff1a;2、rewrite 执行顺序如下&#xff1a;3、rewrite 示例 一、常见的…

B-3:Linux 系统渗透提权

B-3&#xff1a;Linux 系统渗透提权 任务环境说明&#xff1a; 服务器场景&#xff1a;Server2204&#xff08;关闭链接&#xff09; 用户名&#xff1a;hacker 密码&#xff1a;123456 1.使用渗透机对服务器信息收集&#xff0c;并将服务器中 SSH 服务端口号作为 flag 提 …

Java工厂模式(随笔)

前言&#xff1a;Java工厂模式是一种创建型设计模式&#xff0c;它提供了一种将对象创建过程封装到一个单独的类中的方式&#xff0c;这个类就是被称为‘工厂类’&#xff0c;它根据特定的条件来决定应该创建哪个对象&#xff01; 文章目录&#xff1a; 三大工厂模式介绍特殊工…

计算机网络第二章——物理层(上)

提示&#xff1a;男儿何不带吴钩&#xff0c;收取关山五十州 文章目录 2.1.1 物理层基本概念知识引导物理层接口特征 2.1.2 数据通信基础知识数据通信相关术语数据通信系统要考虑的问题三种通信方式串行传输&并行传输同步传输&异步传输 脑图时刻 2.1.3 数据通信基础知识…

Google Play上架aab保姆级教程(纯aab上架/已上架apk转aab上架)

0、上传密钥 & 应用签名密钥 “Google 会使用上传证书验证您的身份&#xff0c;并使用您的应用签名密钥为 APK 签名以进行分发” 以上为官方解释。 2021年8月起&#xff0c;上传google play的应用必须以aab格式&#xff0c;aab的签名流程要比之前apk的复杂一些。需要上传…

如何真正有效地应对项目中的需求变更?

需求变更在奉行唯快不破的互联网公司&#xff0c;可算程序员头号噩梦&#xff0c;“996”直接元凶。 阿里口号拥抱变化。既然需求变更无法被消灭&#xff0c;就要通过学习&#xff0c;掌握更好应对需求变更方法。 1 常见的需求变更流程 先要发起变更申请&#xff0c;由变更委…

从IO多路复用到redis线程模型

文章目录 Unix IO模型分类阻塞IO - Blocking IO非阻塞IO - NoneBlocking IOIO多路复用 - IO multiplexing信号驱动IO - signal driven IO异步IO - asynchronous IO同步与异步的定义阻塞与非阻塞的定义 IO多路复用有哪些实现IO多路复用的大致实现selectpollepoll redis的线程模型…

Python实战基础19-异常处理及程序调试

1、异常概述 在程序运行过程中&#xff0c;经常会遇到各种各样的错误&#xff0c;这些错误统称为“异常”。 这些异常有的是由于开发者将关键字敲错&#xff0c;这类错误产生的是SyntaxError:invalid syntax&#xff08;无效语法&#xff09;&#xff0c;这将直接导致程序不能…

3.二进制高可用安装k8s 1.23集群(生产级)

二进制高可用安装k8s集群(生产级) 本文档适用于kubernetes1.23 节点 Etcd Cluster Etcd是一个数据库,k8s做的一些变更啥的都会存到Etcd中 如果集群比较大建议与master节点分装,单独装Etcd master节点 master分为几个重要的组件 你所有的流量都会经过Kube-APIServer Co…

排序算法——希尔排序图文详解

文章目录 希尔排序基本思想整体插入思想预排序结论 代码实现实现代码直接插入排序与希尔排序的效率比较测试代码&#xff1a; 时间复杂度 希尔排序 注1&#xff1a;本篇是基于对直接插入排序法的拓展&#xff0c;如果对直接插入法不了解&#xff0c;建议先看看直接插入排序 注…

Learning C++ No.27 【布隆过滤器实战】

引言 北京时间&#xff1a;2023/5/31/22:02&#xff0c;昨天的计算机导论考试&#xff0c;三个字&#xff0c;哈哈哈&#xff0c;摆烂&#xff0c;大致题目都是一些基础知识&#xff0c;但是这些基础知识都是非常非常理论的知识&#xff0c;理论的我一点不会&#xff0c;像什么…