当前位置: 首页 > news >正文

Qt基于信号量QSemaphore实现的生产者消费者模型

在 Qt 中,信号量(QSemaphore)是一种用于控制对共享资源访问的同步工具。它允许一定数量的线程同时访问共享资源,适合用于生产者-消费者模型。

代码实现

#include <QCoreApplication>
#include <QThread>
#include <QSemaphore>
#include <QDebug>
#include <QQueue>
#include <QMutex>

const int BUFFER_SIZE = 5;

QQueue<int> buffer; // 共享缓冲区
QSemaphore freeSpace(BUFFER_SIZE); // 空闲空间信号量
QSemaphore usedSpace(0); // 已使用空间信号量
QMutex mutex; // 保护缓冲区的互斥锁

// 生产者线程
class Producer : public QThread {
protected:
    void run() override {
        for (int i = 0; i < 10; ++i) {
            freeSpace.acquire(); // 等待空闲空间
            mutex.lock();
            buffer.enqueue(i);
            qDebug() << "Produced:" << i;
            mutex.unlock();
            usedSpace.release(); // 增加已使用空间
            QThread::msleep(100); // 模拟生产耗时
        }
    }
};

// 消费者线程
class Consumer : public QThread {
protected:
    void run() override {
        for (int i = 0; i < 10; ++i) {
            usedSpace.acquire(); // 等待已使用空间
            mutex.lock();
            int value = buffer.dequeue();
            qDebug() << "Consumed:" << value;
            mutex.unlock();
            freeSpace.release(); // 增加空闲空间
            QThread::msleep(200); // 模拟消费耗时
        }
    }
};

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    Producer producer;
    Consumer consumer;

    producer.start();
    consumer.start();

    producer.wait();
    consumer.wait();

    return app.exec();
}

代码说明

1、共享资源:

buffer 是一个共享的队列,用于存储生产者生成的数据。

2、信号量:

freeSpace:表示缓冲区中的空闲空间数量,初始值为 BUFFER_SIZE。
usedSpace:表示缓冲区中已使用的空间数量,初始值为 0。

3、互斥锁:

mutex 用于保护对 buffer 的访问,确保生产者和消费者不会同时操作缓冲区。

4、生产者线程:

调用 freeSpace.acquire() 等待空闲空间。
使用 mutex.lock() 保护缓冲区,将数据放入缓冲区。
调用 usedSpace.release() 增加已使用空间。

5、消费者线程:

调用 usedSpace.acquire() 等待已使用空间。
使用 mutex.lock() 保护缓冲区,从缓冲区取出数据。
调用 freeSpace.release() 增加空闲空间。

为什么必须使用两个信号量?

1、精准控制两种状态:

freeSpace 确保生产者在缓冲区未满时才能生产。
usedSpace 确保消费者在缓冲区非空时才能消费。

2、避免竞争条件:

生产者和消费者通过不同的信号量等待和通知,避免因共享单一信号量导致的条件误判。

为什么不能只用一个 QSemaphore?

1、同步问题:

生产者需要等待缓冲区有空闲空间才能生产数据。
消费者需要等待缓冲区有数据才能消费数据。
如果只用一个 QSemaphore,无法同时满足这两个条件。

2、线程安全问题:

如果生产者请求资源(减少信号量),消费者释放资源(增加信号量),可能会导致信号量的值不符合实际缓冲区状态。
例如,生产者可能在缓冲区已满时继续生产,消费者可能在缓冲区为空时继续消费,导致数据不一致。

3、无法区分状态:

一个 QSemaphore 只能表示一种状态(如空闲空间或已使用空间),无法同时表示两种状态。

相关文章:

  • 【Vue3】浅谈setup语法糖
  • 手机隐私数据彻底删除工具:回收或弃用手机前防数据恢复
  • golang安装(1.23.6)
  • 智能家居遥控革命!昂瑞微HS6621EM:用「芯」定义AIoT时代的语音交互标杆
  • 【0011】HTML其他文本格式化标签详解(em标签、strong标签、b标签、i标签、sup标签、sub标签......)
  • 【企业场景】上线的项目如何进行限流
  • 为什么打开串口会发送两次指令(加强版)
  • JeeWMS graphReportController.do SQL注入漏洞复现(CVE-2025-0392)
  • 【OpenCV C++】以时间命名存图,自动检查存储目录,若不存在自动创建, 按下空格、回车、Q、S自动存图
  • 18440二维差分
  • 【开源-鸿蒙土拨鼠大理石系统】鸿蒙 HarmonyOS Next App+微信小程序+云平台
  • 微信小程序读取写入NFC文本,以及NFC直接启动小程序指定页面
  • AIP-155 请求标识
  • 标签使用笔记
  • sqli-lab
  • 【SpringBoot】数据访问技术spring Data、 JDBC、MyBatis、JSR-303校验
  • 使用通义万相Wan2.1进行视频生成
  • 钉钉宜搭智能车辆管理系统:AIoT与低代码融合的数字化解决方案
  • 基于Three.js的3D赛车游戏开发实战详解
  • Vue 3 路由管理实战:构建多页面博客导航 - 掌握 Vue Router 实现 SPA 页面跳转
  • 软件开发网站能做seo吗/全国疫情最新名单
  • 优秀网站建设设计/宁波seo网络推广主要作用
  • ug.wordpress.org/电脑优化系统的软件哪个好
  • 985短网址生成器/seo薪酬如何
  • 做yahoo代拍网站公司/新媒体销售好做吗
  • node.js做网站开发/软文的目的是什么