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。
相关推荐
实心儿儿10 小时前
Qt — 信号和槽
qt
江湖人称菠萝包11 小时前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter8-绘图
笔记·qt·qt5
西西弗Sisyphus12 小时前
Qt 实现一个 水波进度球
c++·qt·c
RAN11426760081 天前
1.3第一个程序的介绍
开发语言·qt
实心儿儿1 天前
Qt — 命名方式、坐标系
qt
小小龙学IT1 天前
Qt QPainter 2D 绘图系统深度解析:从画笔到渲染引擎适
c++·qt
深兰科技1 天前
深兰科技受邀参与第二届中国(南宁)—东盟人工智能场景应用对接会,深化AI国际合作
人工智能·qt·r语言·scala·symfony·智能机器人·深兰科技
实心儿儿1 天前
Qt — 对象树
qt
Quz2 天前
QML Repeater 数据模型:ListModel 与 C++ QAbstractListModel
qt
Quz2 天前
QML Repeater 基础用法:整数、JS 数组、字符串数组三种模型
qt