Qt中线程同步类介绍(一)

Qt中线程同步类介绍(一)

Qt中实现线程同步的类主要是:QMutex、QMutexLoker、QReadWriteLocker、QReadLocker、QWriteLocker、QSemaphore、QWaitCondition和QSemaphore。

一、基本概念

QMutex和QMutexLocker

QMutex 和QMutexLocker是基于互斥量的线程同步类。

(1)QMutex

主要提供一下3个函数:

lock():加锁。如果锁已经被其他线程占用,当前线程会阻塞(等待) 直到锁被释放;

unlock():解锁。必须和lock()成对调用,否则会导致死锁;

trylock():尝试加锁。如果锁被占用,不会阻塞,直接返回false;如果加锁成功返回true(适合不想阻塞的场景)。

QMutex简单使用示例:

c++ 复制代码
#include <QCoreApplication>
#include <QMutex>
#include <QThread>
#include <QDebug>

QMutex mutex; // 全局互斥锁
int sharedValue = 0; // 共享资源

void threadFunc()
{
    for (int i = 0; i < 5; ++i)
    {
        mutex.lock(); // 加锁:进入临界区
        sharedValue++; // 操作共享资源,此时只有当前线程能执行
        qDebug() << QThread::currentThreadId() << "sharedValue:" << sharedValue;
        mutex.unlock(); // 解锁:离开临界区,其他线程可加锁

        QThread::msleep(10); // 模拟耗时操作
    }
}

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

    // Set up code that uses the Qt event loop here.
    // Call a.quit() or a.exit() to quit the application.
    // A not very useful example would be including
    // #include <QTimer>
    // near the top of the file and calling
    // QTimer::singleShot(5000, &a, &QCoreApplication::quit);
    // which quits the application after 5 seconds.

    // If you do not need a running Qt event loop, remove the call
    // to a.exec() or use the Non-Qt Plain C++ Application template.

    QThread t1;
    QThread t2;
    QObject::connect(&t1, &QThread::started, threadFunc);
    QObject::connect(&t2, &QThread::started, threadFunc);
    t1.start();
    t2.start();

    return a.exec();
}

注意点:

必须保证lock()unlock()成对出现!如果在临界区中抛出异常、提前 return,会导致unlock()无法执行,其他线程永远拿不到锁(死锁)。

(2)QMutexLocker

QMutexLocker是 Qt 提供的RAII 风格的锁管理类 (RAII:资源获取即初始化),可以理解为QMutex的 "自动管家"------ 它会在创建时自动加锁,销毁时自动解锁,彻底避免手动加解锁的漏写 / 错写问题。

核心逻辑:

构造函数:接收一个QMutex对象的指针 / 引用,自动调用mutex->lock();

析构函数:当QMutexLocker对象超出作用域(比如函数结束、遇到break/return),自动调用mutex->unlock()。

使用示例,替换上面的QMutex

C++ 复制代码
#include <QMutexLocker>
#include <QThread>
#include <QDebug>

QMutex mutex;
int sharedValue = 0;

void threadFunc() 
{
    for (int i = 0; i < 5; ++i) 
    {
        QMutexLocker locker(&mutex); // 自动加锁
        sharedValue++;
        qDebug() << QThread::currentThreadId() << "sharedValue:" << sharedValue;
        // 无需手动解锁!locker析构时自动解锁(即使这里写return也不影响)
        QThread::msleep(10);
    } // locker超出作用域,析构→自动解锁
}

额外实用方法

unlock():手动提前解锁(比如临界区提前结束);

relock():重新加锁(如果提前解锁后需要再次保护资源)。

(3)QMutex vs QMutexLocker 核心对比

特性 QMutex QMutexLocker
加解锁方式 手动调用 lock ()/unlock () 自动加锁(构造)、自动解锁(析构)
安全性 低(易漏写 unlock ()) 高(RAII 机制,避免死锁)
代码复杂度 高(需手动管理成对调用) 低(一行代码搞定加解锁)
使用场景 简单场景 / 需手动控制解锁 绝大多数多线程临界区保护(推荐优先用)

二、总结

  1. QMutex 是基础互斥锁,提供手动加解锁能力,核心作用是保护共享资源,但需严格保证lock()/unlock()成对调用;
  2. QMutexLockerQMutex的封装,基于 RAII 机制自动管理锁的生命周期,能避免因异常 / 提前退出导致的死锁,是 Qt 中推荐的锁使用方式;
  3. 实际开发中,优先使用 QMutexLocker,仅在需要手动精细控制解锁时机时(比如临界区中间需要临时解锁)才直接用 QMutex。
相关推荐
树欲静而风不止慢一点吧2 小时前
Qt5/6版本对应的Emscripten版本
开发语言·qt
LYOBOYI1233 小时前
qt的事件传播机制
java·前端·qt
prettyxian6 小时前
【QT】Qt从零入门指南:创建你的第一个GUI程序
开发语言·qt
不会c嘎嘎7 小时前
QT中的常用控件(一)
开发语言·qt
枫叶丹410 小时前
【Qt开发】Qt系统(一)-> 定时器 QTimerEvent 和 QTimer
c语言·开发语言·数据库·c++·qt·系统架构
林政硕(Cohen0415)11 小时前
ARM Linux Qt Widget 虚拟键盘输入法移植
linux·arm开发·qt·键盘·输入法
养一回月亮!16 小时前
使用Qt实现简单绘图板:鼠标绘制与擦除功能详解
开发语言·qt
cpp_learners19 小时前
Qt Windows版本的《智能鼠标点击器》
windows·qt·鼠标点击器
Liu-Eleven1 天前
Qt/C++开发嵌入式项目日志库选型
开发语言·c++·qt