C++多线程和循环队列

假设我们不使用互斥锁,并且我们在两个线程中分别调用 enqueuedequeue 方法。

#include <iostream>
#include <thread>template <typename T> class Queue {private:static constexpr int MAX_SIZE = 1000;T items[MAX_SIZE];int front, rear;public:Queue() : front(-1), rear(-1) {}bool isEmpty() { return front == -1; }void enqueue(const T &value) {if ((rear + 1) % MAX_SIZE == front) {std::cout << "Queue is full" << std::endl;return;}if (front == -1) {front = rear = 0;} else {rear = (rear + 1) % MAX_SIZE;}items[rear] = value;}T dequeue() {if (front == -1) {std::cout << "Queue is empty" << std::endl;return T{};}T removedItem = items[front];if (front == rear) {front = rear = -1;} else {front = (front + 1) % MAX_SIZE;}return removedItem;}
};void producer(Queue<int> &q) {for (int i = 0; i < 100; ++i) {q.enqueue(i);std::this_thread::sleep_for(std::chrono::milliseconds(10));}
}void consumer(Queue<int> &q) {while (true) {if (!q.isEmpty()) {int value = q.dequeue();std::cout << "Dequeued: " << value << std::endl;}std::this_thread::sleep_for(std::chrono::milliseconds(15));}
}int main() {Queue<int> q;std::thread t1(producer, std::ref(q));std::thread t2(consumer, std::ref(q));t1.join();t2.join();return 0;
}

在这个例子中,没有使用任何锁机制来保护 enqueuedequeue 操作。下面是可能出现的问题的几种情况:

  1. 数据竞争: 两个线程可能同时访问和修改 frontrear 变量,导致它们的值不一致。例如:

    • 线程 A (producer) 在插入一个新元素时,刚刚修改了 rear,还没来得及更新 items[rear]
    • 线程 B (consumer) 可能同时读取 front 并进行删除操作,这时 frontrear 之间的关系可能不一致。
  2. 丢失数据: 由于没有同步,enqueue 操作可能会覆盖队列中的数据,而 dequeue 操作可能会读取错误的数据或读取到无效的数据。例如:

    • 线程 A 在 rear 更新前被中断,线程 B 读取到的是尚未正确插入的数据;
    • 线程 B 在 front 更新前被中断,线程 A 插入的数据可能会被错误地覆盖。
  3. 未定义行为: 多线程并发修改共享数据时,可能会导致程序行为不可预测甚至崩溃。

用互斥锁来解决这个问题


#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>template <typename T> class ThreadSafeQueue {private:static constexpr int MAX_SIZE = 1000;T queue[MAX_SIZE];int front, rear;std::mutex mtx;             // 互斥量,用于保护共享数据std::condition_variable cv; // 条件变量public:ThreadSafeQueue() : front(-1), rear(-1) {}void push(const T &value) {std::lock_guard<std::mutex> lock(mtx);if ((rear + 1) % MAX_SIZE == front) {std::cout << "Queue is full" << std::endl;return;}if (front == -1) {front = rear = 0;} else {rear = (rear + 1) % MAX_SIZE;}queue[rear] = value;// 通知等待的消费者线程cv.notify_one();}T pop() {// 等待数据准备就绪std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [this] { return front != -1; }); // 等待条件变量满足// 处理数据T removedItem = queue[front];if (front == rear) {front = rear = -1;} else {front = (front + 1) % MAX_SIZE;}return removedItem;}
};void producer(ThreadSafeQueue<int> &tsq) {for (int i = 0;; ++i) {std::cout << "Producing: " << i << std::endl;tsq.push(i);std::this_thread::sleep_for(std::chrono::milliseconds(1));}
}void consumer(ThreadSafeQueue<int> &tsq) {while (1) {int value = tsq.pop();std::cout << "Consuming: " << value << std::endl;}
}
int main() {ThreadSafeQueue<int> tsq;std::thread t1(producer, std::ref(tsq));std::thread t2(consumer, std::ref(tsq));t1.join();t2.join();
}

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

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

相关文章

算法导论 总结索引 | 第四部分 第十七章:摊还分析

1、数据结构的一个操作序列中 所执行的 所有操作的平均时间&#xff0c;来评估该操作的代价。摊还分析 不同于平均情况分析&#xff0c;它并不涉及概率&#xff0c;它可以保证最坏情况下每个操作的平均性能 它是一种平均情况下的 性能分析方法&#xff0c;用于 评估一系列操作的…

Java多态练习(2024.7.10)

动物类 package KeepPets20240710;public class Animal {private String color;private int age;public Animal(){}public Animal(String color, int age) {this.color color;this.age age;}public String getColor() {return color;}public void setColor(String color) {t…

开源流程表单设计器都有哪些值得一提的优势?

如果需要提质、增效、降本&#xff0c;不妨来了解下低代码技术平台、开源流程表单设计器的功能和优势特点。想要实现流程化办公&#xff0c;低代码技术平台是助力增效的理想工具。功能灵活、操作方便、好维修、可视化操作等优势都是其深受行业喜爱的优势特点。通过本文&#xf…

Errno2:No such file or directory,在当前文件确实没有该图片,怎么解决?

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

常用网络概念

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ​​ 目录 了解组织 局域网技术 …

高深宽比刻蚀和纳米级图形化推进存储器的路线图

随着市场需求推动存储器技术向更高密度、更优性能、新材料、3D堆栈、高深宽比 &#xff08;HAR&#xff09; 刻蚀和极紫外 &#xff08;EUV&#xff09; 光刻发展&#xff0c;泛林集团正在探索未来三到五年生产可能面临的挑战&#xff0c;以经济的成本为晶圆厂提供解决方案。 …

数组常用的方法

数组,是JavaScript中的一种数据格式,在JavaScript中经常使用。作为一名前端工程师,掌握Array的用法非常重要! 那么,常用的数组方法你知道几个呢? 如果不知道也没有关系,今天这篇文章将汇总详细介绍Array中常用的一些方法,一起来学习一下吧! 01、push 功能:向数组…

谷歌浏览器插件开发笔记0.1.022

谷歌浏览器插件开发笔记0.1.000 示例文件manifest.jsonpopup.htmloptions.jsoptions.htmlcontent.jsbackground.js 网页按钮快捷键插件参考链接 示例文件 共计有6个常用的文件 manifest.json background字段&#xff1a;随着浏览器的打开而打开&#xff0c;随着浏览器的关闭…

Qt 实战(2)搭建开发环境 | 2.2、.pro文件详解

文章目录 一、.pro文件详解1、.pro文件的作用2、项目管理3、编译配置4、依赖管理5、平台支持6、自动化编译7、示例8、总结 前言&#xff1a; 在Qt开发环境中&#xff0c;.pro文件是一个非常重要的项目文件&#xff0c;它全称为项目管理文件&#xff08;Project file&#xff09…

DHCPIP、Lan IPLan Static IP

一、什么是DHCP? DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种网络协议&#xff0c;用于自动分配IP地址和其他网络配置给设备&#xff08;如计算机、手机、网络打印机等&#xff09;&#xff0c;使得设备能够在网络上进行通信。 IP地址分配&#…

【进阶篇-Day7:JAVA中Date、LocalDate等时间API的介绍】

目录 1、概述2、JDK8(-) 时间类2.1 Date类&#xff1a;&#xff08;1&#xff09;构造方法&#xff1a;&#xff08;2&#xff09;常用成员方法&#xff1a; 2.2 SimpleDateFormat类&#xff1a;2.3 总结&#xff1a;2.4 Calendar类介绍&#xff1a; 3、JDK8() 时间类3.1 日历类…

fortran简单排序算法,对一维、二维矩阵进行正序或倒序排序

fortran简单排序算法&#xff0c;对一维、二维矩阵进行正序或倒序排序 0. 引言1. 算法实现1.1 一维数组排序1.2 二维数组排序1.2 module文件 2. 结语 0. 引言 排序算法是计算机科学中的一项重要技术&#xff0c;它将一组数据按照特定的顺序排列起来。排序算法有很多种&#xff…

设计模式探索:责任链模式

1. 什么是责任链模式 责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下&#xff1a; 避免将一个请求的发送者与接收者耦合在一起&#xff0c;让多个对象都有机会处理请求。将接收请求的对象连接成一条链&#xff0c;并且沿着这条链传递请求&…

samout 最新版本state 逐层控制加速收敛

代码 import torch import numpy as npclass MaxState(torch.nn.Module):def __init__(self, hidden_dim, heads, win):super(MaxState, self).__init__()assert hidden_dim % heads 0, "Hidden size must be divisible by the number of heads."self.head_size h…

【C++深度学习】多态(概念虚函数抽象类)

✨ 疏影横斜水清浅&#xff0c;暗香浮动月黄昏 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…

第2章 大话 ASP.NET Core 入门

第1章 框架学习的基石与实战策略 链接 第2章 大话 ASP.NET Core 入门 1.什么是ASP.NET Core框架 ASP.NET Core是一个超级棒的框架&#xff0c;它是免费的&#xff0c;你可以在任何主流的系统上&#xff0c;比如Windows、Linux或macOS上使用它&#xff0c;而且它是完全开放源…

appium环境准备

前言: 本系列教程会从软件的基本安装开始,最终目的是通过完成几个案例后, 大家实现自由抓取App中想要的资源。 本系列以后会更的: Appium基本使用及控制真机及安卓模拟器Mitmproxy抓包工具的基本使用Fiddler抓包软件的基本使用 了解了以上的基本操作,我们就可进行手机资源…

Splunk Enterprise路径遍历漏洞风险通告

今日&#xff0c;亚信安全CERT监控到安全社区研究人员发布安全通告&#xff0c;披露了Splunk Enterprise 路径遍历漏洞(CVE-2024-36991)。该漏洞发生在9.2.0<version<9.2.2&#xff0c;9.1.0<version<9.1.5&#xff0c;以及9.0.0<version<9.0.10的windows版本…

3102.力扣每日一题7/9 Java(TreeMap)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 TreeMap详解 解题思路 解题方法 时间复杂度 空间复杂度 Code T…

【Python】 已解决:ModuleNotFoundError: No module named…

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named… 一、分析问题背景 在使用Python进行开发时&#xff0c;有时会遇到“ModuleNotFoundError: No module named…”这样的…