49 C++ 多个线程之间共享资源问题。lock , unlock

前提,我们要补充一个知识点。再使用类成员函数做为 线程启动的入口,第二个参数可以传递对象 和 对象地址,如下:

类似这样:thread readthread(&Teacher164::readfunc,tea);thread readthread(&Teacher164::readfunc,&tea);

那么 这两种 有啥区别?

//当我们在构造一个 thread的时候,如下代码对应 readthread,writethread,
//如果第二个参数传递的是 Teacher164对象 tea,那么会有copy 构造函数的调用。


//如果 我们在传递第二个参数的时候, 传递的是Teacher164对象的tea的地址,相当于多个线程中都会共享这个tea,这才会让在 Teacher164类中的list是同一个,才有共享数据的可能性。

class Teacher164 {public://共享数据 存在list中list<int> msgListQueue;
public://读取 共享数据的线程方法void readfunc() {int readcount = 0;while (true && readcount!=100000) {//只要不为空,就可以读取数据if (!msgListQueue.empty()) {int readvalue = msgListQueue.front();//每次都读取第一个cout << "读取到的值为" << readvalue << endl;msgListQueue.pop_front();//删除第一个元素readcount++;}else {cout << "没有读取到值" << endl;}}}//写入 共享数据的线程方法void writefunc() {for (size_t i = 0; i < 100000; i++){msgListQueue.push_back(i);//每次都写到末尾cout << "写入元素的值为" << i << endl;}}public:Teacher164() {cout << "Teacher164 构造方法 this = " << this << endl;}Teacher164(const Teacher164 & obj) {cout << "Teacher164 copy 构造方法 this = " << this << "  obj = " << &obj<< endl;}~Teacher164() {cout << "Teacher164 析构函数 this = " << this << endl;}
};//当我们在构造一个 thread的时候,如下代码对应 readthread,writethread,
//如果第二个参数传递的是 Teacher164对象 tea,那么会有copy 构造函数的调用。
//如果 我们在传递第二个参数的时候, 传递的是Teacher164对象的tea的地址,相当于多个线程中都会共享这个tea,这才会让在 Teacher164类中的list是同一个,才有共享数据的可能性。void main() {Teacher164 tea;thread readthread(&Teacher164::readfunc,tea);thread writethread(&Teacher164::writefunc, tea);readthread.join();writethread.join();//如上,调用的时候,tea是值传递的时候,会调用 copy 构造函数//Teacher164 构造方法 this = 00000092A277F508//	Teacher164 copy 构造方法 this = 000002713BA6C420  obj = 00000092A277F508//	Teacher164 copy 构造方法 this = 000002713BA75310  obj = 00000092A277F508//	Teacher164 析构函数 this = 000002713BA6C420//	Teacher164 析构函数 this = 000002713BA75310//	Teacher164 析构函数 this = 00000092A277F508cout << "=========================" << endl;
}

//传递 是地址:  thread readthread1(&Teacher164::readfunc, &tea1); 

结果是:只要使用的 &tea1 的线程,都使用的同一个tea(地址是一样的,没有copy 构造函数调用),这就有可能让其共享数据

void main(){Teacher164 tea1;thread readthread1(&Teacher164::readfunc, &tea1);thread writethread1(&Teacher164::writefunc, &tea1);//thread 的构造方法第二个参数 可以是地址,如果是地址,那么 readthread1 和 writethread1的传递就是同一个 teacher//  Teacher164 构造方法 this = 000000265F4FFB68//	Teacher164 析构函数 this = 000000265F4FFB68}

对于只读的资源,所有线程都可以一起去读,这是线程安全的。

但是如果有些线程是读资源,有些线程是写资源,那么就要注意线程之间的资源共享问题了。

//我们先把问题简化,假设有2个线程,一个线程 读数据,一个线程写数据。但是运行确一直没有问题。
//于是搞4个线程,2个读数据,2个写数据

有问题的代码

class Teacher164 {public://共享数据 存在list中list<int> msgListQueue;
public://读取 共享数据的线程方法void readfunc() {int readcount = 0;while (true && readcount!=100000) {//只要不为空,就可以读取数据if (!msgListQueue.empty()) {int readvalue = msgListQueue.front();//每次都读取第一个cout << "读取到的值为" << readvalue << endl;msgListQueue.pop_front();//删除第一个元素readcount++;}else {cout << "没有读取到值" << endl;}}}//写入 共享数据的线程方法void writefunc() {for (size_t i = 0; i < 100000; i++){msgListQueue.push_back(i);//每次都写到末尾cout << "写入元素的值为" << i << endl;}}public:Teacher164() {cout << "Teacher164 构造方法 this = " << this << endl;}Teacher164(const Teacher164 & obj) {cout << "Teacher164 copy 构造方法 this = " << this << "  obj = " << &obj<< endl;}~Teacher164() {cout << "Teacher164 析构函数 this = " << this << endl;}
};void main() {cout << "=========================" << endl;Teacher164 tea1;thread readthread1(&Teacher164::readfunc, &tea1);thread writethread1(&Teacher164::writefunc, &tea1);//thread 的构造方法第二个参数 可以是地址,如果是地址,那么 readthread1 和 writethread1的传递就是同一个 teacherthread readthread2(&Teacher164::readfunc, &tea1);thread writethread2(&Teacher164::writefunc, &tea1);readthread1.join();readthread2.join();writethread1.join();writethread2.join();}

fix方案,使用mutex(锁子),结合lock() 和 unlock()方法

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

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

相关文章

C# 基础入门

第二章 C# 语法基础 2-1 C# 中的关键字 关键字&#xff0c;是一些被C#规定了用途的重要单词。 在Visual Studio的开发环境中&#xff0c;关键字被标识为蓝色&#xff0c;下图代码中&#xff0c;用红方框圈出的单词就是关键字。 关键字 class &#xff0c;这个关键字的用途是…

Linux下编写zlg7290驱动(1)

大家好&#xff0c;今天给大家介绍Linux下编写zlg7290驱动(1)&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 在智能仪表中&#xff0c;经常会用到键盘、数码管等外设。因此&…

一个div内有好几个p元素,如何清空 / 删除 p元素的数据

一个div内有好几个p元素&#xff0c;如何清空p元素的数据 若要清空一个 div 内多个 p 元素的数据&#xff0c;可以遍历该 div 中的所有 p 元素&#xff0c;并设置它们的 textContent 或 innerHTML 属性为空字符串&#xff0c;这样即可清空它们的内容。 以下是一个示例&#x…

Redis学习指南(5)-Redis-Desktop的安装

前言 Redis-Desktop是一款开源的Redis图形化管理工具&#xff0c;它提供了直观的用户界面&#xff0c;方便用户对Redis数据库进行可视化管理。本文将介绍Redis-Desktop的安装步骤以及基本的使用方式。 安装 Redis-Desktop Redis-Desktop支持多个平台&#xff0c;包括Windows…

【Java语言基础②】Java基本语法——Java程序基本格式,注释,标识符,常量

通过前面的学习&#xff0c;大家对Java语言有了一个基础认识&#xff0c;但现在还无法使用Java语言编写程序&#xff0c;要熟练使用Java语言编写程序&#xff0c;必须充分掌握Java语言的基础知识。今天咱们就来聊一聊Java的基本语法。 1.java程序的基本格式 Java程序代码必须…

Spring Boot 3 + Vue 3实战:引入数据库实现用户登录功能

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;创建数据库&#xff08;二&#xff09;创建用户表&#xff08;三&#xff09;后端项目引入数据库1、添加相关依赖2、用户实体类保持不变3、编写应用配置文件4、创建用户映射器接口5、创建用户服务类6、修改登录控制…

剑指offer题解合集——Week3day6

文章目录 剑指offerWeek3周六&#xff1a;栈的压入、弹出序列AC代码思路&#xff1a; 周六&#xff1a;不分行从上往下打印二叉树AC代码思路&#xff1a; 剑指offerWeek3 周六&#xff1a;栈的压入、弹出序列 题目链接&#xff1a;栈的压入、弹出序列 输入两个整数序列&…

element plus自定义组件表单校验

方式一&#xff1a; import { formContextKey, formItemContextKey } from "element-plus";// 获取 el-form 组件上下文 const formContext inject(formContextKey, void 0); // 获取 el-form-item 组件上下文 const formItemContext inject(formItemContextKey, …

NLP论文阅读记录 - 2021 | WOS 使用深度强化学习及其他技术进行自动文本摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1. Seq2seq 模型2.2.强化学习和序列生成2.3.自动文本摘要 三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 Auto…

Java:常见算法

认识算法 什么是算法&#xff1f; 解决某个实际问题的过程和方法 学习算法的技巧 先搞清楚算法的流程直接去推敲如何写代码 排序算法 冒泡排序 每次从数组中找出最大值放在数组的后面去。 实现冒泡排序的关键步骤分析 确认总共需要做几轮&#xff1a;数组的长度-1每轮比较…

【java】创建打印数组的方法并调用

java的数组和Python不一样&#xff0c;不能直接用print打印&#xff0c;而如果每次都用循环的方法&#xff0c;比较麻烦&#xff0c;就直接创建一个类&方法&#xff0c;每次用的时候直接调用。 public class list_deal {public static void printArray(int[] arr){for (in…

Python实现对角但非同一性协方差结构回归模型(WLS算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 WLS回归分析是一种常用的回归分析方法&#xff0c;通过对数据进行加权处理&#xff0c;可以更准确地评…

构造函数的初始化列表

一、什么是初始化列表 初始化列表&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个"成员变量"后面跟 一个放在括号中的初始值或表达式。 class Date { public:Date(int year, int month, int day): _year(year), _month(m…

VSCode编写 C/C++ 程序

VSCode 全称 Visual Studio Code&#xff0c;是微软出的一款轻量级代码编辑器&#xff0c;免费、开源而且功能强大。它支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性&#xff0c;支持插件扩展&#xff0c;并…

Day02

今日任务&#xff1a; 977 有序数组的平方209 长度最小的子数组59 螺旋矩阵Ⅱ 977 有序数组的平方 题目链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/ 双指针问题&#xff0c;以及数组本身时有序的&#xff1b; 思路&#xff1a; 左、右两个…

SG-8101CGA 系列 (晶体振荡器 可编程 可用 +125°C )

SG-8101CGA是可编程晶体振荡器&#xff0c;具有CMOS输出&#xff0c;适用于汽车&#xff0c;同时&#xff0c;该系列还提供相同的频率和其他参数的轻松编程能力&#xff0c;符合AEC-Q100标准&#xff0c;具有出色的电磁兼容性和稳定性&#xff0c;可以在各种环境下使用。外部尺…

Linux的DHCP工作原理和dns服务器

目录 一、DHCP原理 1.DHCP的好处 2.DHCP的分配方式 3.实验 二、dns服务器 1.什么是dns 2.dns域名解析 3、在内网搭建dns 一、DHCP原理 DCHP工作原理使用C/S架构 &#xff08;1&#xff09;第一步&#xff0c;客户端广播发送一个discover报文寻找DHCP服务器。 &#…

cf919Div2C题题目总结

Problem - C - Codeforces 这道题其实是一道数学题。 先看第一个变量&#xff0c;也就是我们要求的答案k的数量&#xff0c;但看k是很好确定它的限制条件的&#xff0c;要想均匀分成k份&#xff0c;n%k必须为0&#xff0c;有了k&#xff0c;我们再来看m&#xff0c;对于a(1)和…

牛客周赛 Round 28 解题报告 | 珂学家 | 组合数学 + 离散化树状数组

前言 整体评价 还是E稍微有点意思&#xff0c;新周赛好像比预期要简单一些, _. 欢迎关注 珂朵莉 牛客周赛专栏 珂朵莉 牛客小白月赛专栏 A. 小红的新周赛 思路: 模拟 #include <bits/stdc.h>using namespace std;int main() {int res 0;for (int i 0; i < 6; i…