c++ qt获取电脑的内存_Qt官方示例信号量

演示Qt多线程的信号量操作编程。

  生产者将数据写入缓冲区,直到到达缓冲区末尾为止,然后从头开始重新开始,覆盖现有数据。使用者线程读取生成的数据,并将其写入标准错误。

  信号量比互斥量可以具有更高的并发级别。如果对缓冲区的访问由QMutex保护,则使用者线程无法与生产者线程同时访问缓冲区。但是,使两个线程同时在缓冲区的不同部分上工作并没有什么害处。

  该示例包括两个类:ProducerConsumer。两者都继承自QThread。用于在这两个类之间进行通信的循环缓冲区以及保护它的信号量是全局变量。

  使用QSemaphore解决生产者-消费者问题的替代方法是使用QWaitConditionQMutex。如需看更多请查看Qt的"Wait Conditions Example"示例。

全局变量

  让我们从回顾循环缓冲区和相关的信号量开始:

const int DataSize = 100000;

const int BufferSize = 8192;
char buffer[BufferSize];

QSemaphore freeBytes(BufferSize);
QSemaphore usedBytes;

  DataSize是生产者将生成的大量数据。为了使示例尽可能简单,我们将其设为常量。BufferSize是循环缓冲区的大小。它小于DataSize,表示生产者将在某个时候到达缓冲区的末尾并从头开始重新启动。

  为了使生产者和消费者同步,我们需要两个信号量。该freeBytes信号控制缓冲的"自由"区域(该区域的生产者还没有装满数据或消费者已经读取了)。useBytes信号量控制缓冲区的"已用"区域(生产者已填充但使用者尚未读取的区域)。

  信号量共同确保了生产者在使用方之前不会超过BufferSize字节,并且确保使用方从未读取过生产者尚未生成的数据。

  freeBytes信号量使用BufferSize初始化,因为最初整个缓冲区为空。useBytes信号量初始化为0(如果未指定默认值)。

生产者类

  让我们回顾一下Producer该类的代码:

class Producer : public QThread
{
public:
    void run() override{
        for (int i = 0; i             freeBytes.acquire();
            buffer[i % BufferSize] = "ACGT"[QRandomGenerator::global()->bounded(4)];
            usedBytes.release();
        }
    }
};

  生产者生成DataSize字节数据。在将字节写入循环缓冲区之前,它必须使用freeBytes信号量获取"空闲"字节。如果消费者没有跟上生产者的步伐,调用QSemaphore::acquire()将会在这里阻塞。

  最后,生产者使用usedBytes信号量释放一个字节。"空闲"字节已成功转换为"已使用"字节,供消费者读取。

消费者类

  现在转到Consumer类:

class Consumer : public QThread
{
    Q_OBJECT
public:
    void run() override{
        for (int i = 0; i             usedBytes.acquire();
            fprintf(stderr, "%c", buffer[i % BufferSize]);
            freeBytes.release();
        }
        fprintf(stderr, "\n");
    }
};

现在转到Consumer类:

class Consumer : public QThread
{
    Q_OBJECT
public:
    void run() override{
        for (int i = 0; i             usedBytes.acquire();
            fprintf(stderr, "%c", buffer[i % BufferSize]);
            freeBytes.release();
        }
        fprintf(stderr, "\n");
    }
};

  该代码与生产者非常相似,除了这次我们获得一个"已用"字节并释放一个"空闲"字节,而不是相反。

main函数

  在main函数中,我们创建两个线程并调用QThread::wait()以确保两个线程在退出之前都有时间完成:

int main(int argc, char *argv[]){
    QCoreApplication app(argc, argv);
    Producer producer;
    Consumer consumer;
    producer.start();
    consumer.start();
    producer.wait();
    consumer.wait();
    return 0;
}

  那么当我们运行程序时会发生什么呢?最初,生产者线程是唯一可以做任何事情的线程。消费者被阻止等待usedBytes信号量被释放(其初始available()计数为0)。一旦生产者将一个字节放入缓冲区中,freeBytes.available()BufferSize-1usedBytes.available()等于1。此时,可能会发生两件事:消费者线程接管并读取该字节,或者生产者线程获得第二个字节。

  本示例中提供的生产者-消费者模型使编写高度并发的多线程应用程序成为可能。在多处理器计算机上,该程序的运行速度可能是等效的基于互斥锁的程序的两倍,因为两个线程可以同时在缓冲区的不同部分处于活动状态。

  「请注意」,尽管并非总是能实现这些好处的。获取和释放 QSemaphore 需要花费成本。实际上,将缓冲区划分为块并操作块而不是单个字节可能是值得的。缓冲区大小也是必须根据实验仔细选择其参数。

关于更多

  • 「QtCreator软件」可以找到:aeb258090ef0618f0e7317adb885fa23.png

  • 或在以下「Qt安装目录」找到:

C:\Qt\{你的Qt版本}\Examples\{你的Qt版本}\corelib\threads\semaphores
  • 「相关链接」
https://doc.qt.io/qt-5/qtcore-threads-semaphores-example.html
  • Qt君公众号回复『Qt示例』获取更多内容。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值