QWaitCondition和QMutex详细介绍

一.概念

QWaitCondition 和 QMutex 是 Qt 框架中用于实现多线程同步的重要类。它们通常一同使用,以确保在多线程环境中对共享资源的安全访问。下面是这两个类的详细介绍及示例代码。

  1. QMutex(互斥量)

定义:

QMutex 是一个互斥量,用于保护对共享资源的访问,确保在同一时间只有一个线程可以访问该资源。使用 QMutex 可以避免因为多个线程同时修改同一数据而导致的数据不一致性问题。

常用功能:

  • lock():加锁,阻塞其他尝试获取同一锁的线程。
  • unlock():解锁,允许其他线程获取该锁。
  • tryLock():尝试加锁,如果无法立即获取锁则返回 false。
  1. QWaitCondition(条件变量)

定义:

QWaitCondition 是一个条件变量,用于在特定条件未满足时,使线程进入等待状态。当条件满足时,可以唤醒处于等待状态的线程。

常用功能:

  • wait(QMutex *mutex):等待条件满足,释放指定的互斥量以允许其他线程访问共享资源。
  • wakeOne():唤醒一个等待的线程。
  • wakeAll():唤醒所有等待的线程。

二.示例代码

下面是一个使用 QMutex 和 QWaitCondition 的简单示例,演示如何安全地在多个线程之间进行同步。

cpp 复制代码
#include <QCoreApplication>  
#include <QThread>  
#include <QMutex>  
#include <QWaitCondition>  
#include <QDebug>  

class WorkerThread : public QThread {  
    Q_OBJECT  

public:  
    WorkerThread() : conditionMet(false) {}  

    void run() override {  
        qDebug() << "Worker thread starting...";  
        QMutexLocker locker(&mutex);  // Lock the mutex  

        // Wait until the condition is met  
        while (!conditionMet) {  
            qDebug() << "Worker thread waiting...";  
            condition.wait(&mutex);  // Wait for the condition to change  
        }  

        // If the condition is met, do some work  
        qDebug() << "Worker thread running...";  
        // Simulate work  
        QThread::sleep(2);  
        qDebug() << "Worker thread finished.";  
    }  

    void setConditionMet() {  
        QMutexLocker locker(&mutex);  // Lock the mutex  
        conditionMet = true;          // Change the condition  
        condition.wakeOne();          // Wake one waiting thread  
    }  

private:  
    QMutex mutex;                   // Mutex for synchronization  
    QWaitCondition condition;       // Condition variable  
    bool conditionMet;             // Condition to be met  
};  

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

    WorkerThread workerThread;  
    workerThread.start();  // Start the worker thread  

    // Simulate some delay before setting the condition  
    QThread::sleep(1);  
    workerThread.setConditionMet();  // Notify the worker thread  

    workerThread.wait();  // Wait for the worker thread to finish  
    return a.exec();  
}  

三.代码解释

  1. WorkerThread 类: 这个类继承自 QThread,并实现了 run() 方法。在 run() 方法中,线程会等待条件变量。

  2. 条件控制:

  • 在 run() 方法中,使用 wait() 方法进入等待状态,并释放互斥量 mutex,以允许其他线程访问共享资源。
  • 当 setConditionMet() 被调用时,它会锁定互斥量,设置 conditionMet 为 true,并调用 wakeOne() 唤醒一个等待的线程。
  1. 主函数:
  • 在主函数中,创建并启动 WorkerThread 实例。
  • 通过 setConditionMet() 方法,在主线程中修改状态,唤醒工作线程。

总结

通过使用 QMutex 和 QWaitCondition,你可以有效地管理多线程中的共享资源访问和条件同步。在实际应用中,这种组合非常强大,可以避免数据竞争和确保线程间的有效沟通。

四.mutable关键字

在 C++ 中,mutable 关键字的目的是允许在 const 成员函数中修改该对象的成员变量。因此,mutable 用于修饰成员变量,在某些情况下是有意义的,尤其是当你想在 const 成员函数中修改某个变量时。

对于 mutable QMutex mutex_;

  1. 用途:
  • 如果你将 mutex_ 声明为 mutable,那么你可以在类的 const 成员函数中对这个互斥量进行加锁和解锁。这样,如果这个类的实例是 const 类型的,但你仍然需要对某些内部状态进行保护(比如状态变量),你就可以使用这个 mutable 的 QMutex。
  1. 例子:
cpp 复制代码
class MyClass {  
public:  
    void doSomething() const {  
        QMutexLocker locker(&mutex_); // 在 const 方法中加锁  
        // 修改其他成员变量或访问共享资源  
    }  

private:  
    mutable QMutex mutex_; // 允许在 const 方法中使用  
    int sharedResource_;  
};  

是否多余?

不多余:

  • 如果给定类会有 const 成员函数,并且那些函数需要锁定 mutex_ 以访问或修改共享状态,那么将 mutex_ 声明为 mutable 是合适的。

多余:

  • 如果类的成员函数不需要被声明为 const,或 mutex_ 的主要作用并不需要在 const 函数中锁定,那么 mutable 就可以认为是不必要的。

结论

总结来说,究竟将 QMutex 声明为 mutable 是否多余,取决于你的类的设计和需求。如果存在 const 成员函数并需要使用互斥量保护共享资源,则使用 mutable 是合理的。如果没有这样的需求,仅仅加锁或解锁的操作在非常规的成员函数中使用,那么 mutable 就沒有必要。

相关推荐
小_太_阳6 分钟前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
向宇it7 分钟前
【从零开始入门unity游戏开发之——unity篇02】unity6基础入门——软件下载安装、Unity Hub配置、安装unity编辑器、许可证管理
开发语言·unity·c#·编辑器·游戏引擎
古希腊掌管学习的神44 分钟前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
赵钰老师44 分钟前
【R语言遥感技术】“R+遥感”的水环境综合评价方法
开发语言·数据分析·r语言
就爱学编程1 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
每天都要学信号1 小时前
Python(第一天)
开发语言·python
TENET信条1 小时前
day53 第十一章:图论part04
开发语言·c#·图论
生信圆桌2 小时前
【生信圆桌x教程系列】如何安装 seurat V5版本R包,最详细安装手册
开发语言·r语言