C++实现多线程三窗口卖票程序

        假设我们有100张门票,有三个售卖窗口,我们希望以多线程的方式将这些票卖出去,这样效率会更高一些。

        首先我们需要有一个全局的门票变量。

int tickts = 100;

        卖票的函数,由于每个窗口卖出一张票都需要花费一些时间,假设是100ms,那么可以通过线程睡眠函数实现这一时间的花费。

void selltickts(int number)
{while (tickts > 0){std::cout << tickts<<std::endl;tickts--;std::this_thread::sleep_for(std::chrono::milliseconds(100));//卖一张票花费100ms}
}

main函数,创建窗口。

int main()
{std::vector < std::thread >v;for (int i = 1; i <= 3; i++){v.push_back(std::thread(selltickts, i));}for (int i = 0; i < 3; i++){v[i].join();}return 0;
}

运行结果如下:

         这个运行结果显然是出问题的,基本上每张票都重复售卖了3次。这主要是因为我们使用了tickts--;这一操作,--和++这两个运算符,本身就是线程不安全的,它们都是由三条汇编机器指令组成的。实际上,一个线程在执行一个函数时,不一定会将一个函数的一行代码都完整执行掉,比如tickts--就没有完整执行,但是它一定会将一行代码中的一行汇编指令完整执行掉,执行完了这条汇编指令之后,这个线程就有可能将自己的时间片归还给操作系统,自身陷入阻塞状态,等待下次获取时间片后进行执行剩下的汇编指令。这样就会导致多个线程同时操作一张门票,三个窗口同时在卖一张门票,这是不允许的,我们需要将这三个线程设置为互斥状态,这样它们就不能同时操作一个资源了。这时候就需要用到互斥锁了。

        我们添加一个全局的互斥锁。

std::mutex mtx;

        将售票函数用互斥锁进行锁定。 

void selltickts(int number)
{mtx.lock();while (tickts > 0){std::cout << tickts<<std::endl;tickts--;std::this_thread::sleep_for(std::chrono::milliseconds(100));//卖一张票花费100ms}mtx.unlock();
}

运行程序。

        这次结果虽然正确了,但是由于我们在while循环外面,进行互斥锁定,当有一个线程拿到这个锁时,就进入到了while循环中,其他线程拿不到这个锁,就进入不到while循环里面了,所以这个程序从始至终都只是一个单线程程序,与我们的预期不符合。 

        我们将锁定行为放入while循环中。

void selltickts(int number)
{while (tickts > 0){mtx.lock();std::cout << tickts<<std::endl;tickts--;mtx.unlock();std::this_thread::sleep_for(std::chrono::milliseconds(100));//卖一张票花费100ms}
}

运行程序。

        显然程序还是不对,因为最后卖出了第0张票,这种情况可能是这样的,当票数还有1张时,假如一号窗口进入了while循环拿到了锁,还没有进行--操作,二号窗口也进入了while循环,因为这时候还有1张票,所以二号窗口可以进入while循环,但是拿不到锁,所以while循环里面的代码执行不了,就只能在while循环里面等待锁的到来,于是1号窗口卖完这最后一张票后,将票数减为0,释放了锁,二号直接拿到这个锁,就可以对0继续--了,于是就得到了-1张票。

        解决方式,就是双重条件判断,在while循环里面再次判断一次票数。

void selltickts(int number)
{while (tickts > 0){mtx.lock();if(tickts>0){std::cout << tickts << std::endl;tickts--;}mtx.unlock();std::this_thread::sleep_for(std::chrono::milliseconds(100));//卖一张票花费100ms}
}

        运行结果。

 

        这次总算达到了,我们想要的结果。

        但是这段代码还是有一些隐患,假如我while的if语句里面有一个return语句的话,整个程序就变成一个死锁程序了,一个线程拿到锁后并且触发了这个return,就不会释放这个锁了。要解决这个问题,我们需要用到智能锁。

void selltickts(int number)
{while (tickts > 0){{std::lock_guard<std::mutex>loc(mtx);if (tickts > 0){std::cout <<number<<"号窗口卖出了第"<< tickts << "号票"<<std::endl;tickts--;}}std::this_thread::sleep_for(std::chrono::milliseconds(100));//卖一张票花费100ms}
}

        由于lock_guard析构是离开一个作用域才会触发的,我们可以给它一个作用域(大括号),代表卖完了这张牌,这把锁就自动释放掉了,这样就可以有效避免死锁问题了。

        运行结果。

         达到了我们想要的效果,三个窗口都在卖票,票数没有异常。

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

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

相关文章

springboot的启动流程原理

一:入口简介: 首先,分析启动流程,就要 找到入口. 启动流程的入口方法就是这个run方法: 点进去之后就是这样: 主要分为了两个步骤: 1.创建springBootApplication对象 2.运行SpringApplication#run(java.lang.String...)方法; 上面说了主要分为两个步骤,那么接下…

day02-JavaScript-Vue

1 JavaScript html完成了架子&#xff0c;css做了美化&#xff0c;但是网页是死的&#xff0c;我们需要给他注入灵魂&#xff0c;所以接下来我们需要学习JavaScript&#xff0c;这门语言会让我们的页面能够和用户进行交互。 1.1 介绍 通过代码/js效果演示提供资料进行效果演…

PCIE-TS1/TS2,变量总结

1.标准TS1/TS2 2.EQ TS1/TS2 3.Modified TS1/TS2 Modified TS1/TS2 是什么&#xff1f;Modify了什么&#xff1f;为什么要Modify&#xff1f;非 PCIe 协议运行在 PCIe PHY 上或发送 TS Message 时&#xff0c;在 LTSSM 部分子状态采用 Modified TS1/TS2。允许发送 Modified …

6.画面渲染及背景-《篮球比赛展示管理系统》现场管理员角色操作手册

通过[特效实验室]及[更换背景] 对整个展示界面的底部图层进行动画渲染。此功能是平台的一大特色。一般用在选手上场或颁奖等。用户可以根据现场情况&#xff0c;妥善发挥。背景图片及其特效&#xff0c;应该在比赛之前设置好。

HarmonyOS 开发

环境 下载IDE 代码 import { hilog } from kit.PerformanceAnalysisKit; import testNapi from libentry.so; import { router } from kit.ArkUI; import { common, Want } from kit.AbilityKit;Entry Component struct Index {State message: string Hello HarmonyOS!;p…

遗传算法与深度学习实战(7)——使用遗传算法解决N皇后问题

遗传算法与深度学习实战&#xff08;7&#xff09;——使用遗传算法解决N皇后问题 0. 前言1. N 皇后问题2. 解的表示3. 遗传算法解决 N 皇后问题小结系列链接 0. 前言 进化算法 (Evolutionary Algorithm, EA) 和遗传算法 (Genetic Algorithms, GA) 已成功解决了许多复杂的设计…

GitHub的未来:在微软领导下保持独立与AI发展的平衡

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

20240821 每日AI必读资讯

&#x1f3ae;《黑神话&#xff1a;悟空》震撼上线&#xff0c;英伟达AI技术立功&#xff01; - 中国游戏史上的奇迹&#xff1a;《黑神话&#xff1a;悟空》预售销售额达3.9亿元&#xff0c;刷新国产游戏预售纪录。 - 游戏美学效果惊人&#xff1a;孙悟空形象深入人心&#…

你知道手机零部件尺寸检测的重要性吗?

手机零部件作为手机制造行业的基础&#xff0c;其品质的优劣直接关系到行业的发展&#xff0c;所以加强手机精密零部件尺寸检测非常重要。如今&#xff0c;手机零部件变得更加精细&#xff0c;对质量的要求也在不断提高&#xff0c;随着生产规模逐渐扩大&#xff0c;传统的检测…

网络安全防渗透实战指南【策略、代码与最佳实践】

网络安全防渗透实战指南【策略、代码与最佳实践】 引言 随着互联网的迅猛发展&#xff0c;网络安全问题日益突出。渗透攻击作为网络攻击的一种常见手段&#xff0c;给企业和个人带来了巨大的威胁和损失。因此&#xff0c;如何有效防止渗透攻击成为网络安全领域的重要课题。本…

【python报错解决】ImportError: DLL load failed while importing win32gui: 找不到指定的程序

在 Python 中安装 pywin32 库 pip install pywin32安装完成后找到自己的 Python 根目录&#xff0c;在该目录下打开命令行。 在命令行中输入&#xff1a; python.exe Scripts/pywin32_postinstall.py -install执行后显示以下信息&#xff0c;即问题解决。 Parsed argumen…

订单到期关闭如何实现?

目录 一、被动关闭 二、定时任务 三、JDK自带的DelayQueue 四、Netty的时间轮 五、Kafka的时间轮 六、RocketMQ延迟消息 七、RabbitMQ死信队列 八、RabbitMQ插件 九、Redis过期监听 十、Redis的Zset 十一、Redisson 在电商、支付等系统中&#xff0c;一般都是先创建…

单因子年化23.7%,基于deap的因子挖掘,我改进了fitness和metrics方案(附python代码和数据)

原创文章第626篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 我们目前投入使用的因子挖掘&#xff0c;基于两个框架&#xff0c;deap和gplearn&#xff0c;deap做一点点改动&#xff0c;就可以完美应用于多标的截面因子挖掘。而gplearn如果要支…

C#使用Modbus TCP通讯PLC,实现读写寄存器

一、创建一个Moudbus类&#xff0c;引入NModbus和Modbus这两个包 #region ModbusTCPpublic class NmodbusTcpHelper{// 静态成员变量&#xff0c;用于存储TcpClient实例private static TcpClient tcpClient null;// 静态成员变量&#xff0c;用于存储ModbusIpMaster实例privat…

案例 | 生产制造中的直线度测量

关键词&#xff1a;直线度测量仪,直线度 生产中不仅需要评价产品的外观尺寸&#xff0c;还需要对直线度&#xff08;弯曲度&#xff09;等尺寸加以测量。作为一种评价产品直度的重要指标——直线度&#xff0c;能够对其进行检测是非常重要的。 关于直线度&#xff0c;对于一些弯…

数字人的形象克隆与语音克隆是伪需求

形象克隆与语音克隆技术&#xff0c;在当前的环境上已经可以成熟的实现&#xff0c;但真的解决了痛点问题吗&#xff1f; 普通人或者一般的公司克隆自己内部人的形象有必要吗&#xff1f;对外界而言&#xff0c;克隆的形象与虚拟的形象并无二致&#xff0c;本身并没有什么知名…

Spring Boot 集成 swagger 3.0 指南

Spring Boot 集成 swagger 3.0 指南 一、Swagger介绍1.springfox-swagger 22.SpringFox 3.0.0 发布 二、Spring Boot 集成 swagger 3.01. 添加Maven依赖2. 创建配置类配置Swagger2.1 创建SwaggerConfig 配置类2.1 创建TestInfoConfig信息配置类 3. 在你的Controller上添加swagg…

《黑神话:悟空》的发布是否能打开元宇宙游戏世界的门

四年漫长等待&#xff0c;8月20日&#xff0c;国产3A游戏巨制《黑神话&#xff1a;悟空》正式上线并彻底引爆全球市场。这背后不仅是中国游戏史的里程碑&#xff0c;也将为元宇宙的未来夯实地基&#xff01; 游戏上线后&#xff0c;热度持续飙升&#xff0c;成为了社交媒体和游…

while循环中OLED显示中断中的数据不正确

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

HDRP管线下的开放世界游戏与跨平台优化,《仙剑世界》万字分享

《仙剑世界》作为仙剑 IP 系列的最新⻓篇⼒作&#xff0c;从故事和剧情上延续了仙剑的精髓。在仙剑 33 年的世界观下&#xff0c;《仙剑世界》打造出了⼀个由浪漫唯美的江南全景、磅礴恢弘的蜀⼭、神秘苗疆等区域构成的 384 平⽅公⾥完整的⽆缝开放⼤世界。以东⽅题材为起点&am…