尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Qt 一次性把多线程实现同步方式说清楚

Qt 一次性把多线程实现同步方式说清楚
📅 发布时间:2026/7/22 10:05:20

概念(为何需要同步)

1.多个线程同时读写共享资源(全局/静态内存变量、堆内存动态分配对象、文件/IO/网络句柄、外设资源等),执行顺序不确定,导致数据错乱、崩溃;

2.同步主要是为了保证共享资源互斥访问、线程等待/唤醒、有序执行;

3.测试(没添加同步)

main.cpp

#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QReadWriteLock> #include <QReadLocker> #include <QWriteLocker> #include <QWaitCondition> #include <QSemaphore> #include <QAtomicInt> #include <QAtomicPointer> #include <QAtomicInteger> #include <QtConcurrent/QtConcurrent> #include <QDebug> #include <atomic> int g_count_mutex = 0; void mutexTask() { qDebug() << "子线程ID:" << QThread::currentThreadId(); for (int i = 0; i < 10000; ++i) { g_count_mutex++; QThread::msleep(1); } } void demo_QMutex() { g_count_mutex = 0; QFuture<void> t1 = QtConcurrent::run(mutexTask); QFuture<void> t2 = QtConcurrent::run(mutexTask); t1.waitForFinished(); t2.waitForFinished(); qDebug() << "QMutex 最终计数:" << g_count_mutex; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); demo_QMutex(); return 0; //return a.exec(); }

一、方式1

1.QMutex基础互斥锁:

1)保证同一时间仅一个线程进入临界区,保护共享变量读写;

2)API:

--lock(): 加锁,已被占用则阻塞线程,直到释放;

--tryLock(): 非阻塞尝试加锁,获取成功返回true,失败立即返回false;

--tryLock(int timeout): 带超时,超时内拿不到锁返回false;

--unlock(): 释放锁,必须与lock成对调用。

2.测试

main.cpp

//全局共享变量 + 互斥锁 QMutex g_mutex; int g_count_mutex = 0; void mutexTask() { qDebug() << "子线程ID:" << QThread::currentThreadId(); for (int i = 0; i < 10000; ++i) { g_mutex.lock(); g_count_mutex++; g_mutex.unlock(); } } void demo_QMutex() { g_count_mutex = 0; QFuture<void> t1 = QtConcurrent::run(mutexTask); QFuture<void> t2 = QtConcurrent::run(mutexTask); t1.waitForFinished(); t2.waitForFinished(); qDebug() << "QMutex 最终计数:" << g_count_mutex; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); demo_QMutex(); return 0; //return a.exec(); }

二、方式2

1.QMutexLocker(RAII 自动锁):

1)栈对象构造时自动lock,离开作用域(return/异常/花括号结束)自动unlock,无需手动释放;

2.测试

main.cpp

#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QReadWriteLock> #include <QReadLocker> #include <QWriteLocker> #include <QWaitCondition> #include <QSemaphore> #include <QAtomicInt> #include <QAtomicPointer> #include <QAtomicInteger> #include <QtConcurrent/QtConcurrent> #include <QDebug> #include <atomic> //全局共享变量 + 互斥锁 QMutex g_mutex; int g_count_mutex = 0; void mutexLockerTask() { qDebug() << "子线程ID:" << QThread::currentThreadId(); for (int i = 0; i < 10000; ++i) { QMutexLocker locker(&g_mutex); //RAII自动加锁/解锁 g_count_mutex++; //QThread::msleep(1); } } void demo_QMutexLocker() { g_count_mutex = 0; QFuture<void> t1 = QtConcurrent::run(mutexLockerTask); QFuture<void> t2 = QtConcurrent::run(mutexLockerTask); t1.waitForFinished(); t2.waitForFinished(); qDebug() << "QMutexLocker 最终计数:" << g_count_mutex; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); demo_QMutexLocker(); return 0; //return a.exec(); }

三、方式3

1.QReadWriteLock读写锁:

1)多个线程可同时获取读锁(读和读不冲突);

2)写锁独占: 有线程持有读锁/写锁时,写线程阻塞;持有写锁时,所有读写线程阻塞;

3)配套RAII工具: QReadLocker、QWriteLocker;

4)API:

--lockForRead(): 获取读锁;

--lockForWrite(): 获取写锁;

--tryLockForRead(int t = 0);

--tryLockForWrite(int t = 0);

--unlock();

2.测试

main.cpp

#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QReadWriteLock> #include <QReadLocker> #include <QWriteLocker> #include <QWaitCondition> #include <QSemaphore> #include <QAtomicInt> #include <QAtomicPointer> #include <QAtomicInteger> #include <QtConcurrent/QtConcurrent> #include <QDebug> #include <atomic> QReadWriteLock g_rwLock; int g_data_rw = 0; //读线程 void readTask() { for (int i = 0; i < 100; ++i) { QReadLocker lock(&g_rwLock); //读锁,允许多线程同时读 qDebug() << "读值:" << g_data_rw; QThread::msleep(5); } } //写线程 void writeTask() { for (int i = 0; i < 100; ++i) { QWriteLocker lock(&g_rwLock); //写锁,独占访问 g_data_rw++; qDebug() << "写入值:" << g_data_rw; QThread::msleep(10); } } void demo_QReadWriteLock() { g_data_rw = 0; QFuture<void> r1 = QtConcurrent::run(readTask); QFuture<void> r2 = QtConcurrent::run(readTask); QFuture<void> w1 = QtConcurrent::run(writeTask); r1.waitForFinished(); r2.waitForFinished(); w1.waitForFinished(); qDebug() << "QReadWriteLock 最终值:" << g_data_rw; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); demo_QReadWriteLock(); return 0; //return a.exec(); }

四、方式4

1.QWaitCondition条件变量:

1)线程主动阻塞等待某个条件成立,其他线程修改条件后唤醒等待线程,实现线程间等待/通知,必须配合QMutex使用;

2)API:

--wait(QMutex*, unsigned long timeout): 释放锁,阻塞等待唤醒,超时自动返回;

--wakeOne(): 随机唤醒1个等待线程;

--wakeAll(): 唤醒全部等待线程。

2.测试

main.cpp

#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QReadWriteLock> #include <QReadLocker> #include <QWriteLocker> #include <QWaitCondition> #include <QSemaphore> #include <QAtomicInt> #include <QAtomicPointer> #include <QAtomicInteger> #include <QtConcurrent/QtConcurrent> #include <QDebug> #include <atomic> QMutex g_condMutex; QWaitCondition g_cond; int g_buffer = 0; bool g_hasData = false; //消费者 void consumerTask() { QMutexLocker lock(&g_condMutex); // while 循环防止虚假唤醒 while (!g_hasData) { g_cond.wait(&g_condMutex); } qDebug() << "消费数据:" << g_buffer; g_hasData = false; g_cond.wakeOne(); //通知生产者可以继续生产 } //生产者 void producerTask(int val) { QMutexLocker lock(&g_condMutex); while (g_hasData) { g_cond.wait(&g_condMutex); } g_buffer = val; g_hasData = true; qDebug() << "生产数据:" << g_buffer; g_cond.wakeOne(); } void demo_QWaitCondition() { g_hasData = false; QFuture<void> consumer = QtConcurrent::run(consumerTask); QThread::msleep(100); QFuture<void> producer = QtConcurrent::run(producerTask, 999); consumer.waitForFinished(); producer.waitForFinished(); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); demo_QWaitCondition(); return 0; //return a.exec(); }

五、方式5

1.QSemaphore信号量:

1)内置计数器,控制有限资源的并发访问,本质是带计数的条件变量;

2)API:

--acquire(n): 申请n个资源,资源不足则阻塞;

--release(n): 释放n个资源,计数器 + n;

--available(): 返回当前剩余资源数量。

2.测试

main.cpp

#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QReadWriteLock> #include <QReadLocker> #include <QWriteLocker> #include <QWaitCondition> #include <QSemaphore> #include <QAtomicInt> #include <QAtomicPointer> #include <QAtomicInteger> #include <QtConcurrent/QtConcurrent> #include <QDebug> #include <atomic> QSemaphore g_sem(2); // 最多允许2个线程同时进入临界区 void semTask(int id) { g_sem.acquire(); // 占用1个资源,超出上限则阻塞 qDebug() << "任务" << id << "进入临界区"; QThread::msleep(1000); qDebug() << "任务" << id << "离开临界区"; g_sem.release(); // 释放资源 } void demo_QSemaphore() { QFuture<void> t1 = QtConcurrent::run(semTask, 1); QFuture<void> t2 = QtConcurrent::run(semTask, 2); QFuture<void> t3 = QtConcurrent::run(semTask, 3); QFuture<void> t4 = QtConcurrent::run(semTask, 4); t1.waitForFinished(); t2.waitForFinished(); t3.waitForFinished(); t4.waitForFinished(); qDebug() << "QSemaphore 全部任务结束"; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); demo_QSemaphore(); return 0; //return a.exec(); }

六、方式6

1.QBasicAtomic/std::atomic原子变量(无锁同步):

1)无锁,CPU 硬件指令保证单个变量原子读写,不需要加锁,性能最高;

2)仅支持基础类型:int、long、指针。

2.测试

main.cpp

#include <QCoreApplication> #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QReadWriteLock> #include <QReadLocker> #include <QWriteLocker> #include <QWaitCondition> #include <QSemaphore> #include <QAtomicInt> #include <QAtomicPointer> #include <QAtomicInteger> #include <QtConcurrent/QtConcurrent> #include <QDebug> #include <atomic> //Qt原子变量 QBasicAtomicInt g_qtAtomic = Q_BASIC_ATOMIC_INITIALIZER(0); //C++标准原子变量 std::atomic<int> g_stdAtomic{0}; void atomicTask() { for (int i = 0; i < 5000; ++i) { g_qtAtomic.ref(); // Qt原子自增 g_stdAtomic.fetch_add(1);// C++原子自增 } } void demo_Atomic() { g_qtAtomic = 0; g_stdAtomic = 0; QFuture<void> t1 = QtConcurrent::run(atomicTask); QFuture<void> t2 = QtConcurrent::run(atomicTask); t1.waitForFinished(); t2.waitForFinished(); qDebug() << "QBasicAtomicInt 计数:" << g_qtAtomic.load(); qDebug() << "std::atomic 计数:" << g_stdAtomic.load(); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); demo_Atomic(); return 0; //return a.exec(); }

七、开发工具及Qt版本

开发工具:Qt Creator 4.10.2

Qt版本:Qt_5_12_6

相关新闻

  • AI模型适用场景匹配度评估:3步精准定位你的业务该用LLM、Diffusion还是传统ML
  • 【论文解读】复数CVNet:跳过 FFT,Jetson 上 2.75 ms 如何完成雷达手势识别?
  • 线上核验系统焕新教程|2026宝玑全国维修点线上查询渠道升级完整攻略 - 亨得利腕表服务中心

最新新闻

  • HTTP 404错误解析与优化实践指南
  • 毕业生必看!档案存放 +管理全指南 - 慧办好
  • iPhone查找功能全攻略:从设置到应急响应
  • AI Agent开发指南:从原理到实践应用
  • TI TM4C1292NCZAD ARM Cortex-M4F MCU:工业网关与实时控制开发实战
  • 私有云存储速度到底能跑多快?

日新闻

  • AI云原生实战05-金融AI上云最难的不是技术,是“不出事“——TCE银行风控架构拆解
  • 2026年GEOSEO优化公司选型深度测评:五大硬核标准严选,这六家重塑搜索增长新格局 - 品牌前沿专家
  • **核验!2026年7月卡地亚香港**售后网点地址及服务电话公告 - 卡地亚服务中心

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号