qt double 相减不为0_Qt线程同步单生产者多消费者
序
单生产者单消费者大家应该已经掌握了。上一篇使用的是QMutex跟QWaitCondition。
如果你的C++编译器版本比较高的话,那就可以使用C++11的 std::condition_variable了
代码
这次对比单生产者单消费者,我们多了mutex来进行消费者之间的同步。这样就可以写单生产者多消费者了。
这是代码中多的一个锁,用于同步消费者。
std::mutex mutexConsumer; //消费者用来同步用的
上代码,这是线程同步需要的变量
struct ItemRepository{ std::deque<int> itemQueue; //缓冲区 const int MaxSize = 10; // 仓库所容纳的产品最大个数 int itemCounterUse = 0; //消费者用了多少 std::mutex mutex;// 互斥量,保护产品缓冲区 std::mutex mutexConsumer; //消费者用来同步用的 std::condition_variable bufferNotFull; // 条件变量, 指产品仓库缓冲区不为满 std::condition_variable bufferNotEmpty; // 条件变量, 指产品仓库缓冲区不为空}gItemRepository; // 产品库全局变量,生产者和消费者操作该变量.
这里是实现代码
class Producer : public QThread{ Q_OBJECTpublic: Producer(QObject *parent = NULL) : QThread(parent) { } // 生产 产品 void ProduceItem(ItemRepository &itemRepo, int item){ std::unique_lock<std::mutex> lock(itemRepo.mutex); if (itemRepo.itemQueue.size() == itemRepo.MaxSize) { itemRepo.bufferNotFull.wait(lock); qDebug()<<"product has full"<<endl; }
//#ifdef Q_OS_WIN// Sleep(1000);//#endif
itemRepo.itemQueue.push_back(item); // 仓库放入产品 itemRepo.bufferNotEmpty.notify_all(); // 通知消费者仓库不为空 }
void run() override{ for (int i = 1; i <= kItemsToProduce; i++) { ProduceItem(gItemRepository, i); { qDebug()<<"procut------------"<endl; } } }};class Consumer : public QThread{ Q_OBJECTpublic: Consumer(QObject *parent = NULL) : QThread(parent) { }// 消费 产品int ConsumeItem(ItemRepository &itemRepo){int data;std::unique_lock<std::mutex> lock(itemRepo.mutex);if (itemRepo.itemQueue.empty()) { itemRepo.bufferNotEmpty.wait(lock); } data = itemRepo.itemQueue.front(); itemRepo.itemQueue.pop_front(); itemRepo.bufferNotFull.notify_all();return data; }void run() override{while (true) {int item = 0;std::unique_lock<std::mutex> lock(gItemRepository.mutexConsumer); // 仓库产品消费计数器保持多线程互斥if (gItemRepository.itemCounterUse { item = ConsumeItem(gItemRepository); // 消费产品 gItemRepository.itemCounterUse++; // 每消费一次进行计数器+1 } lock.unlock();if (this->objectName() == "thread0") {#ifdef Q_OS_WIN Sleep(2000);#endif }else if (this->objectName() == "thread1") {#ifdef Q_OS_WIN Sleep(3000);#endif }else if (this->objectName() == "thread2") {#ifdef Q_OS_WIN Sleep(2000);#endif } qDebug()<<"Consumer------------"<<this->objectName()<<"-----"<endl; } }};
有一点需要注意的是,消费的时候,应该在消费者的外面,所以我打的log是解锁之后sleep。这时候应该及时通知其它消费者线程赶紧调度。这样避免cpu的资源浪费。
稍微吐槽下,目前百度 Qt 单生产者多消费者的例子,十有八九是用Qt的信号量来实现的,可是写那篇文章的人也没有研究明白,那个例子有严重的bug。稍微变通下生产总数跟缓冲区总数就输出有问题了。慎用。
CSDN的文章就是相互抄袭啊。逃)
工程代码在这里
https://github.com/CryFeiFei/Qt_Teach/tree/master/Qt_Teach/Thread_Muliconsmer[1]
参考资料
[1]
https://github.com/CryFeiFei/Qt_Teach/tree/master/Qt_Teach/Thread_Muliconsmer: https://github.com/CryFeiFei/Qt_Teach/tree/master/Qt_Teach/Thread_Muliconsmer
qt double 相减不为0_Qt线程同步单生产者多消费者相关推荐
- qt double 相减不为0_Qt音视频开发25-ffmpeg音量设置
一.前言 音视频的播放.关闭.暂停.继续这几个基本功能,绝大部分人都是信手拈来的搞定,关于音量调节还是稍微饶了下弯弯,最开始打算采用各个系统的api来处理,坐下来发现不大好,系统的支持不完美,比如有些 ...
- Qt之线程同步(生产者消费者模式 - QSemaphore)
简述 生产者将数据写入缓冲区,直到它到达缓冲区的末尾,此时,它将从开始位置重新启动,覆盖现有数据.消费者线程读取数据并将其写入标准错误. Semaphore(信号量) 比 mutex(互斥量)有 ...
- Qt之线程同步(生产者消费者模式 - QWaitCondition)
简述 生产者将数据写入缓冲区,直到它到达缓冲区的末尾,这时,它从开始位置重新启动,覆盖现有数据.消费者线程读取数据并将其写入标准错误. Wait condition(等待条件)比单独使用 mut ...
- Java学习笔记18:Java_Map集合_HashMap集合_可变参数_Stream流_多线程_线程同步_生产者消费者
文章目录 1.Map集合 1.1Map集合概述和特点[理解] 1.2Map集合的基本功能[应用] 1.3Map集合的获取功能[应用] 1.4Map集合的遍历(方式1)[应用] 1.5Map集合的遍历( ...
- Java多线程(实现多线程、线程同步、生产者消费者)
1.实现多线程 1.1简单了解多线程[理解] 是指从软件或者硬件上实现多个线程并发执行的技术. 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能. 1.2并发和并行[理解] 并 ...
- JAVA入门基础进阶(十四)—— 实现多线程、线程同步、生产者消费者
文章目录 1.实现多线程 1.1简单了解多线程[理解] 1.2并发和并行[理解] 1.3进程和线程[理解] 1.4实现多线程方式一:继承Thread类[应用] 1.5实现多线程方式二:实现Runnab ...
- 线程同步 生产者消费者 java_Java线程同步:生产者-消费者 模型(代码示例)
public class ThreadSyn { public static void main(String[] args) { new ThreadSyn(); } public ThreadSy ...
- java double相减_完美解决java double数相加和相减的方案
我就废话不多说了,大家还是直接看代码吧~ /** * double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型 * 整型地方法适合于 ...
- 两个double相减_double类型相减有小数误差
如 :19.9-9.9=9.9999999999999,而不是10double相减会转换成二进制,因double有效位数为 16位这就会出现存储小数位数不够的情况,这种情况下就会出现误差 //两个Do ...
- 线程通信问题--生产者和消费者问题
一.问题引入:首先实现一个线程通信的实例,使用两个线程交替打印输出100以内的数字. 代码实现如下: 1 package com.baozi.exer; 2 3 public class Commun ...
最新文章
- 为什么不应该使用“volatile”类型
- 论文速递:通过模拟大脑-解决深度学习中的灾难性遗忘
- iphone11看信号强度_iPhone11信号怎么样_iPhone11信号差原因|解决办法-太平洋IT百科...
- python中文什么意思-python是什么
- leetcode算法题--圆圈中最后剩下的数字
- Python 处理CSV文件
- Linux多线程之线程同步(条件变量)
- Mars 算法实践——人脸识别 1
- learn mips
- 图神经网络GNN论文2019-2020顶会列表
- clion使用之如何在编译运行多个程序(以cpp为例)
- foxmail邮箱pop3服务器,Foxmail设置POP3邮箱的操作流程
- 北理珠计算机考试,acst
- Android适配全面屏,三星S8的18.9,小米mix全面屏
- 使用Flutter开发Github客户端及学习历程的小结
- RIGOL示波器编程使用
- ifconfig查看网络丢包
- 计算机哪个自考学校好,哪个学校的自考计算机专业本科比较好通过?
- 苏鹏谈TechEd2009
- 三种妙法搞定冗余表数据一致性
热门文章
- J2EE的13个规范之(三) Servlet简单介绍
- 梦断代码读后感——终结
- 卡巴斯基安全软件2014(78三年,逢周一68)时间:2013.10.1-2013.10.31
- 专业化分类服务,引领IDC行业发展新模式
- Apache HBase 最新发布2.0.4 ,分布式数据库
- pycharm的编码问题
- golang:cannot unmarshal number into Go value of type []json.RawMessage
- php中将url中的参数含有%20进行转换或解码
- ERROR: cuvid requested, but not all dependencies are satisfied: ffnvcodec
- 全网首发:研究WORD布局,会意之笑