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。
相关推荐
初次见面我叫泰隆15 小时前
Qt——1、初识Qt
开发语言·c++·qt
一只小bit18 小时前
Qt 事件:覆盖介绍、处理、各种类型及运用全详解
前端·c++·qt·cpp
不会c嘎嘎20 小时前
QT中的事件机制
开发语言·qt
涛起云永20 小时前
Qt 源码编译 -- obj文件无法找到
开发语言·qt
郝学胜-神的一滴21 小时前
Qt自定义TabWidget:实现左侧标签与水平文本布局
开发语言·c++·qt·程序人生
划水的code搬运工小李21 小时前
VOFA修改数据解析GPCHC
开发语言·qt
专注echarts研发20年1 天前
工业级 Qt 业务窗体标杆实现・ResearchForm 类深度解析
数据库·qt·系统架构
世转神风-1 天前
qt-字符串版本与数值版本互转
开发语言·qt
资深流水灯工程师1 天前
基于Python的Qt开发之Pyside6 串口接收数据被分割的解决方案
开发语言·python·qt
羊小猪~~1 天前
【QT】--文件操作
前端·数据库·c++·后端·qt·qt6.3