当前位置: 首页 > ops >正文

面试问题详解十二:Qt 多线程同步:QMutex讲解

在多线程编程中,当多个线程访问共享资源(如全局变量、文件、数据库连接等)时,如果不加控制,会导致 数据竞争(Data Race)不确定的程序行为。为了保证线程安全,我们需要使用同步原语来对共享资源进行保护。

Qt 提供了多种线程同步机制,其中最基本也是最常用的就是 互斥锁(QMutex


一、QMutex 是什么?

QMutex 是 Qt 提供的互斥锁类,用于在线程之间同步访问共享资源。它确保在同一时间只有一个线程可以进入临界区(访问共享资源的代码块)。

常见用法:

  • lock():锁定互斥量。如果已经被其他线程锁定,则当前线程会阻塞等待。
  • unlock():释放互斥量,使其他等待的线程可以继续。
  • tryLock():尝试锁定互斥量,如果无法立即锁定,不会阻塞,直接返回 false

二、使用 QMutex 的基本示例

下面是一个完整的例子:我们创建两个线程去同时增加一个共享的整数变量 counter。通过 QMutex 来保护这个变量,避免并发访问的问题。


1. 项目结构(文件一览)

  • main.cpp:主函数
  • worker.h / worker.cpp:线程类定义与实现

2. 代码详解

worker.h
#ifndef WORKER_H
#define WORKER_H#include <QThread>
#include <QMutex>class Worker : public QThread
{
public:Worker(int id, int* counter, QMutex* mutex);void run() override;private:int m_id;int* m_counter;QMutex* m_mutex;
};#endif // WORKER_H
worker.cpp
#include "worker.h"
#include <QDebug>Worker::Worker(int id, int* counter, QMutex* mutex): m_id(id), m_counter(counter), m_mutex(mutex)
{}void Worker::run()
{for (int i = 0; i < 5; ++i) {m_mutex->lock();  // 加锁,保护共享变量(*m_counter)++;qDebug() << "Thread" << m_id << "incremented counter to" << *m_counter;m_mutex->unlock();  // 解锁msleep(100);  // 模拟耗时操作}
}
main.cpp
#include <QCoreApplication>
#include "worker.h"
#include <QMutex>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int counter = 0;     // 共享资源QMutex mutex;        // 互斥锁保护共享资源Worker thread1(1, &counter, &mutex);Worker thread2(2, &counter, &mutex);thread1.start();thread2.start();thread1.wait();  // 等待线程1完成thread2.wait();  // 等待线程2完成qDebug() << "Final counter value:" << counter;return 0;
}

三、运行效果

程序运行后,两条线程会交替输出增加 counter 的值:

Thread 1 incremented counter to 1
Thread 2 incremented counter to 2
Thread 1 incremented counter to 3
Thread 2 incremented counter to 4
...
Final counter value: 10

由于使用了 QMutex,即使两个线程同时运行,counter 的值也不会出现跳变或错误,确保了线程安全。


四、QMutex 的常见用法与注意事项

✅ 推荐用法:使用 QMutexLocker

为了防止忘记调用 unlock() 导致死锁,Qt 提供了一个辅助类 QMutexLocker,它利用 RAII(资源获取即初始化)原则自动管理锁的释放。

修改 Worker::run() 如下:

void Worker::run()
{for (int i = 0; i < 5; ++i) {QMutexLocker locker(m_mutex);  // 自动加锁和解锁(*m_counter)++;qDebug() << "Thread" << m_id << "incremented counter to" << *m_counter;msleep(100);  // 解锁后执行}
}

只要 locker 对象超出作用域,锁就会自动释放,不再需要手动调用 unlock()


五、总结

  • QMutex 是保护共享资源最常用的同步机制,适用于绝大多数线程同步场景。
  • 加锁时务必注意解锁,否则容易造成死锁。
  • 推荐使用 QMutexLocker 管理互斥锁,避免忘记 unlock()

http://www.xdnf.cn/news/19166.html

相关文章:

  • SystemVerilog学习【七】包(Package)详解
  • FFmpeg音视频处理解决方案
  • 【GaussDB】在逻辑复制中剔除指定用户的事务
  • 【C++】C++ const成员函数与取地址操作符重载
  • 【Leetcode hot 100】21.合并两个有序链表
  • Flutter MVVM+provider的基本示例
  • ceph配置集群
  • VGG改进(6):基于PyTorch的VGG16-SE网络实战
  • “我店模式“当下观察:三方逻辑未变,三大升级重构竞争力
  • 详解常见的多模态大模型指令集构建
  • vue表格底部添加合计栏,且能跟主表同时滑动
  • 「鸿蒙系统的编程基础」——探索鸿蒙开发
  • 机器视觉学习-day12-图像梯度处理及图像边缘检测
  • REST API 是无状态的吗,如何保障 API 的安全调用?
  • 中科院人机交互科研分享-田丰
  • OpenCV 轮廓分析实战:从检测到形状匹配的完整指南
  • 【后端】云服务器用nginx配置域名访问前后端分离项目
  • SpringBoot防止重复提交(2)
  • docker 部署Skywalking
  • 干掉抽取壳!FART 自动化脱壳框架与 Execute 脱壳点解析
  • OpenCV DNN 模块完全指南:从理论基础到实战应用 —— 图像分类与目标检测的深度学习实现(含 Python/C++ 代码与性能分析)
  • 一站式可视化运维:解锁时序数据库 TDengine 的正确打开方式
  • 微信小程序长按识别图片二维码
  • 【C语言】字符函数与字符串函数实战:用法原理 + 模拟实现
  • 零、2025 年软件设计师考试大纲
  • Citrix 零日漏洞自五月起遭积极利用
  • Redis-基数统计、位图、位域、流
  • LangChain.js 实战与原理:用 LCEL 构建可维护的 RAG / Agent 系统(含 4 套 30+ 行代码)
  • 大语言模型生成的“超龄劳动者权益保障制度系统化完善建议(修订版)”
  • Day17(前端:JavaScript基础阶段)