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

发布时间:2026/7/22 9:42:06
Qt 一次性把多线程实现同步方式说清楚 概念(为何需要同步)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; QFuturevoid t1 QtConcurrent::run(mutexTask); QFuturevoid 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(); }一、方式11.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; QFuturevoid t1 QtConcurrent::run(mutexTask); QFuturevoid 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(); }二、方式21.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; QFuturevoid t1 QtConcurrent::run(mutexLockerTask); QFuturevoid 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(); }三、方式31.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; QFuturevoid r1 QtConcurrent::run(readTask); QFuturevoid r2 QtConcurrent::run(readTask); QFuturevoid 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(); }四、方式41.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; QFuturevoid consumer QtConcurrent::run(consumerTask); QThread::msleep(100); QFuturevoid 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(); }五、方式51.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() { QFuturevoid t1 QtConcurrent::run(semTask, 1); QFuturevoid t2 QtConcurrent::run(semTask, 2); QFuturevoid t3 QtConcurrent::run(semTask, 3); QFuturevoid 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(); }六、方式61.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::atomicint 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; QFuturevoid t1 QtConcurrent::run(atomicTask); QFuturevoid 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.2Qt版本:Qt_5_12_6