C++11并发与多线程笔记(4) 创建多个线程、数据共享问题分析、案例代码

news2024/9/25 3:21:58

C++11并发与多线程笔记(4) 创建多个线程、数据共享问题分析、案例代码

  • 1、创建和等待多个线程
  • 2、数据共享问题分析
    • 2.1 只读的数据
    • 2.2 有读有写
    • 2.3 其他特例
  • 3、共享数据的保护案例代码

1、创建和等待多个线程

#include<iostream>
#include<thread>
#include <vector>
using namespace std;
//线程入口函数
void myPrint(int inum) {
	cout << "myPrint线程开始执行了,线程编号= "<<inum << endl;
	// ....doWork
	cout << "myPrint线程结束执行了,线程编号= "<<inum << endl;
}
int main() {
	//1、创建和等待多个线程
	vector<thread> mythreads;
    
	for (int i = 0; i < 10; i++) {
		mythreads.push_back(thread(myPrint, i));//创建10个线程,线程入口函数统一使用myPrint(匿名对象)

	}
	for (auto iter = mythreads.begin(); iter != mythreads.end(); ++iter) {
		iter->join();//等待10个线程都返回
	}
	cout << "I love China!" << endl;
	return 0;
}

  • 多个线程执行顺序是乱的,跟操作系统内部对线程的运行调度机制有关;
  • 主线程等待所有子线程运行结束,最后主线程结束
  • 把thread对象放入到容器里管理,看起来像个thread对象数组,这对一次创建大量的线程并对大量线程进行管理很方便

2、数据共享问题分析

2.1 只读的数据

//线程入口函数
vector<int> g_v = { 1,2,3 };//共享数据,只读,不写
void myPrint(int inum) {
	cout << "id 为 " << this_thread::get_id() << " 的线程 打印g_v的值: " << g_v[0] << g_v[1] << g_v[2] << endl;//只读
	return;
}
int main() {
	vector<thread> mythreads;
	for (int i = 0; i < 10; i++) {
		mythreads.push_back(thread(myPrint, i));
	}
	for (auto iter = mythreads.begin(); iter != mythreads.end(); ++iter) {
		iter->join();//等待10个线程都返回
	}
	cout << "I love China!" << endl;
	return 0;
}

在这里插入图片描述

只读的数据,是安全稳定的,不需要特别什么处理手段。直接读就可以;

2.2 有读有写

有读有写:假设有2个线程,8个线程,如果代码没有特别的处理,那程序肯定崩溃;

最简单的防止崩溃方法:读的时候不能写,写的时候不能读。2个线程不能同时写,8个线程不能同时读

写的动作分10小步,由于任务切换,导致各种诡异的事情发生(最可能的诡异的事情还是崩溃)

2.3 其他特例

  • 数据共享
  • 北京–深圳火车 T123,10个售票窗口卖票 1,2窗口 同时都要订99座

3、共享数据的保护案例代码

网络游戏服务器

  • 两个自己创建的线程,一个线程收集玩家命令(用一个数字代表玩家发来的命令),并把命令数据写到一个队列。
  • 另外一个线程从队列中取出玩家发送来的命令,解析,然后执行玩家需要的动作﹔

vector, list , list跟vector。list:频繁随机插入和删除数据时效率高。vector容器查找效率高,尾部插入效率高。

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

class A {
public:
	//把收到的消息(玩家命令)加入到一个队列的线程
	void inMsgRecvQueue() {
		for (int i = 0; i < 100000; i++) {
			cout << "inMsgRecvQueue()执行,插入一个元素 " << i << endl;
			msgRecvQueue.push_back(i);// 假设这个数字i就是收到的命令,直接弄到消息队列里边来
		}
	}
	//把数据从消息队列中取出的线程
	void outMsgRecvQueue() {
		for (int i = 0; i < 100000; i++) {
			if (!msgRecvQueue.empty()) {
				//消息不为空
				int command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
				msgRecvQueue.pop_front();//移除第一个元素,但不返回
				//.... 这里就考虑处理数据
			}
			else {
				//消息队列为空
				cout << "outMsgRecvQueue()执行,但目前消息队列中为空" << i << endl;
			}
			cout << "end" << endl;
		}
	}
private:
	list<int> msgRecvQueue;//容器,专门用于存放玩家发来的命令
};

int main() {
	A myobja;
	//线程通过对象的成员函数时,第二个参数需要是对象的地址,因为成员函数运行时需要用到this指针
	thread mythreadInMsgRecv(&A::inMsgRecvQueue, &myobja);
	thread mythreadOutMsgRecv(&A::outMsgRecvQueue, &myobja);
	mythreadInMsgRecv.join();
	mythreadOutMsgRecv.join();

	cout << "I love China!" << endl;
	return 0;
}

目前问题:程序不稳定,读写没控制,造成错误
解决方法:引入一个c++解决多线程保护共享数据问题的第一个概念“互斥量”

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

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

相关文章

Scada和lloT有什么区别?

人们经常混淆SCADA&#xff08;监督控制和数据采集&#xff09;和IIoT&#xff08;工业物联网&#xff09;。虽然SCADA系统已经存在多年&#xff0c;但IIoT是一种相对较新的技术&#xff0c;由于其能够收集和分析来自各种设备的大量数据而越来越受欢迎。SCADA和IIoT都用于提高工…

tomcat源码修改与编译

1、获取源码 从github下载其源码&#xff1a;https://github.com/apache/tomcat 2、选择版本 切换到对应版本&#xff08;直接用相对应的Git tag即可&#xff09;&#xff1a; git checkout 9.0.793、修改源代码&#xff0c;并且生成补丁 这里我们以修改去掉新版本的ws的检…

Docker网络与Cgroup硬件资源占用控制

目录 1.dockers的网络模式 1.1 获取容器的进程号 1.2 docker网络模式的特性 1.3 host主机模式 1.4 container模式 1.5 none模式 1.6 bridge 桥接模式 1.6 容器的自定义网络 &#xff08;1&#xff09;未创建自定义网络时&#xff0c;创建指定IP容器的测试 &#xff0…

VBA技术资料MF44:VBA_把数据从剪贴板粘贴到Excel

【分享成果&#xff0c;随喜正能量】人皆知以食愈饥&#xff0c;莫知以学愈愚,生命中所有的不期而遇都是你努力的惊喜.人越纯粹&#xff0c;就越能感受到美。大江、大河、大海、大山、大自然&#xff0c;这些风景从来都不会受“属于谁”的污染&#xff0c;人人都感受到它们的美…

来自句子转换器:转换器和池化组件

一、说明 转换器和池化组件&#xff0c;它们来自 Bert 在 SentenceTransformer 对象中预先训练的模型。 在我之前的文章中&#xff0c;我用拥抱面转换器介绍了预训练模型来计算句子之间的余弦相似性分数。在这篇文章中&#xff0c;我们将深入研究变压器模型的参数。句子转换器对…

Unity 编辑器资源导入处理函数 OnPreprocessTexture:深入解析与实用案例

Unity 编辑器资源导入处理函数 OnPreprocessTexture 用法 点击封面跳转下载页面 简介 在Unity中&#xff0c;我们可以使用编辑器资源导入处理函数&#xff08;OnPreprocessTexture&#xff09;来自定义处理纹理资源的导入过程。这个函数是继承自AssetPostprocessor类的&#x…

.NET Core6.0使用NPOI导入导出Excel

一、使用NPOI导出Excel //引入NPOI包 HTML <input type"button" class"layui-btn layui-btn-blue2 layui-btn-sm" id"ExportExcel" onclick"ExportExcel()" value"导出" />JS //导出Excelfunction ExportExcel() {…

微信小程序OCR插件,实现身份证、行驶证、银行卡、营业执照和驾驶证等识别

随着科技的不断发展&#xff0c;图片识别技术已经成为了当下移动互联网中的热点话题。而基于微信小程序和 OCR 插件的图文识别方案&#xff0c;更是成为了越来越多小程序开发者关注和研究的问题。本文中&#xff0c;我将为大家介绍微信小程序 OCR 插件&#xff0c;帮助大家实现…

并发编程系列-分而治之思想Forkjoin

我们介绍过一些有关并发编程的工具和概念&#xff0c;包括线程池、Future、CompletableFuture和CompletionService。如果仔细观察&#xff0c;你会发现这些工具实际上是帮助我们从任务的角度来解决并发问题的&#xff0c;而不是让我们陷入线程之间如何协作的繁琐细节&#xff0…

Linux学习之基本指令一

在学习Linux下的基本指令之前首先大家要知道Linux下一切皆目录&#xff0c;我们的操作基本上也都是对目录的操作&#xff0c;这里我们可以联想我们是如何在windows上是如何操作的&#xff0c;只是形式上不同&#xff0c;类比学习更容易理解。 目录 01.ls指令 02. pwd命令 0…

Android Ble蓝牙App(六)请求MTU与显示设备信息

前言 在上一篇文章中已经了解了数据操作的方式&#xff0c;而数据交互的字节长度取决于我们手机与蓝牙设备的最大支持长度。 目录 Ble蓝牙App&#xff08;一&#xff09;扫描Ble蓝牙App&#xff08;二&#xff09;连接与发现服务Ble蓝牙App&#xff08;三&#xff09;特性和属…

财报解读:多元化布局,亲亲食品欲摘“果冻之王”头衔?

提及亲亲食品&#xff0c;大多数消费者的印象是其果冻、虾条等产品&#xff0c;而随着消费升级、休闲零食行业竞争的加剧&#xff0c;亲亲食品近年来也想“多条腿走路”&#xff0c;持续进行着产品创新。 不过&#xff0c;在市场看来&#xff0c;承载其转型愿景的新品并未带来…

ORB-SLAM2学习笔记8之特征点提取、生成描述子的ORBextractor

文章目录 0 引言1 特征点提取1.1 提取流程1.2 ORBextractor.cc1.2.1 成员函数1.2.2 成员变量 1.3 构建图像金字塔1.3.1 为什么要构建图像金字塔1.3.2 金字塔参数设置 1.4 提取ORB特征点1.4.1 Fast角点检测1.4.2 特征点提取流程1.4.3 八叉树筛选及非极大值抑制 2 描述子生成2.1 …

【数据集】GRNWRZ V2.0(全球河流网络和相应的水资源分区)介绍及下载

数据介绍 论文&#xff1a;J2022-A data set of global river networks and corresponding water resources zones divisions v2 论文下载地址 GRNWRZV1.0由严登华教授&#xff08;中国水利水电科学研究院&#xff09;团队开发&#xff0c;以全球90mDEM数据为基础&#xff0c;结…

SpringBoot-Mybatis 入门(数据库增删改查)

创建SpringBoot-Mybatis项目 创建新项目&#xff0c;注意Type要选择Maven Spring Boot的版本没啥硬性要求&#xff0c;一般开开发环境 依赖必选MySQL Driver、MyBatis Framework&#xff1b; 选Spring Web是为了辅助未来的web开发&#xff1b; Lombok是个人开发习惯。 配置 …

【C++精华铺】8.C++模板初阶

目录 1. 泛型编程 2. 函数模板 2.1 函数模板的概念及格式 2.2 函数模板的原理 2.3 模板的实例化 2.4 模板参数的匹配原则 3. 类模板 3.1 类模板格式 3.2 类模板的实例化 1. 泛型编程 什么是泛型编程&#xff1f;泛型编程是避免使用某种具体类型而去使用某种通用类型来进行…

FT2000+低温情况下RTC守时问题

1、背景介绍 飞腾2000芯片通过I2C连接一块RTC时钟芯片&#xff08;BellingBL5372&#xff09;来实现麒麟信安系统下后的守时功能。目前BIOS支持UEFI功能&#xff0c;BIOS上电后能获取RTC时间&#xff0c;并将时间写入相应的UEFI变量或内存区域&#xff0c;操作系统上电后使用U…

大模型基础02:GPT家族与提示学习

大模型基础&#xff1a;GPT 家族与提示学习 从 GPT-1 到 GPT-3.5 GPT(Generative Pre-trained Transformer)是 Google 于2018年提出的一种基于 Transformer 的预训练语言模型。它标志着自然语言处理领域从 RNN 时代进入 Transformer 时代。GPT 的发展历史和技术特点如下: GP…

产业园区数字孪生3d可视化全景展示方案

随着数字经济的发展&#xff0c;数字技术给企业发展带来了机遇的同时&#xff0c;也为企业管理带来挑战。比如园区运维&#xff0c;不仅体量大&#xff0c;复杂的运维管理系统&#xff0c;落地难度也较高。那么如何通过数字化手段重塑园区运营&#xff0c;打通园区各业务数据孤…

LimeReport设置当前打印时间

拉一个文本控件&#xff0c;然后填入下面信息&#xff1a; $S{ var curDate new Date(); var strYear curDate.getFullYear().toString(); var strMonth (curDate.getMonth() 1).toString(); var strDay curDate.getDate().toString(); var strHour curDate.getHours().…