QT各种锁及线程同步应用

一.概述

1.在Qt中,主要有以下几种锁的类型:

(1)QMutex(互斥锁):是最常见的锁类型,用于实现简单的互斥访问。可以通过lock()和unlock()手动控制锁的加锁和解锁。

(2)QMutexLocker:是一个RAII类,用于简化对QMutex的加锁和解锁过程。在创建QMutexLocker对象时,会自动加锁,离开作用域时会自动解锁,确保资源在合适的时候被解锁,避免忘记解锁或异常导致未解锁的情况。

(3)QReadWriteLock(读写锁):用于实现读写分离的锁机制,允许多个线程同时读取共享资源,但只有一个线程可以进行写入操作。可以通过lockForRead()和lockForWrite()手动控制读取锁和写入锁。

QReadLocker和QWriteLocker:是QReadWriteLock的RAII类,用于简化对QReadWriteLock的加读锁和加写锁过程。在创建QReadLocker或QWriteLocker对象时,会自动加读锁或加写锁,离开作用域时会自动解锁,确保资源在合适的时候被解锁。

(4)QSemaphore(信号量):允许控制对共享资源的并发访问数量。可以通过acquire()和release()手动控制资源的获取和释放。

(5)QWaitCondition(条件变量):用于线程间的等待和唤醒,允许一个线程等待特定条件的发生,并在其他线程满足条件时发出信号。

总体来说,Qt提供了丰富的锁机制来帮助开发者实现线程安全的并发编程。选择合适的锁类型取决于具体的并发场景和资源访问需求。在使用锁时,一定要小心避免死锁和竞态条件等问题,确保线程间安全的共享资源访问。

同时,使用RAII类(如QMutexLocker、QReadLocker、QWriteLocker)可以简化锁的管理,减少出错的可能性。

2.其他线程同步机制

QThread::wait()

QThread::wait() 是Qt提供的一个线程同步机制,可以用于等待一个线程完成执行。调用该函数会使当前线程阻塞,直到指定的线程完成执行为止。

二.代码示例

1.QMutex(互斥锁)的例子:

#include <QMutex>

QMutex mutex;

int count = 0;

for (int i = 0; i < 1000; ++i) {

mutex.lock();

++count;

mutex.unlock();

}

qDebug() << "Final count:" << count;

2.QMutexLocker的例子:

#include <QCoreApplication>

#include <QMutex>

#include <QMutexLocker>

#include <QDebug>

void run() {

QMutex mutex;

QMutexLocker locker(&mutex);

for (int i = 0; i < 1000; ++i) {

++sharedResource;

}

qDebug() << "Thread" << QThread::currentThreadId() << "finished. Current count:" << sharedResource;

}

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

run();

return a.exec();

}

3.QReadWriteLock(读写锁)的例子:

#include <QCoreApplication>

#include <QReadWriteLock>

#include <QDebug>

#include <QThread>

#include <QMutexLocker>

#include <QRandomGenerator>

// 假设的共享资源

class SharedData {

public:

SharedData() : data(0) {}

void read() const {

// 读取操作,这里只是打印信息

qDebug() << "Thread" << QThread::currentThreadId() << "is reading the data:" << data;

}

void write(int newValue) {

// 写入操作,这里设置新值并打印信息

data = newValue;

qDebug() << "Thread" << QThread::currentThreadId() << "wrote the data:" << data;

}

int data;

};

// 全局的共享数据和读写锁

SharedData sharedData;

QReadWriteLock rwLock;

void readTask() {

// 使用 QReadLocker 自动管理读锁

QReadLocker locker(&rwLock);

sharedData.read();

}

void writeTask(int value) {

// 使用 QWriteLocker 自动管理写锁

QWriteLocker locker(&rwLock);

sharedData.write(value);

}

int main(int argc, char *argv[]) {

QCoreApplication a(argc, argv);

// 创建并启动读取线程

QThread readThread;

QObject::connect(&readThread, &QThread::started, readTask);

readThread.start();

// 等待读取线程开始

readThread.sleep(1); // 示例中简单等待,实际应用中可能需要更复杂的同步机制

// 在主线程中执行写入任务

writeTask(27);

// 等待读取线程完成

readThread.wait();

return a.exec();

}

4.QSemaphore(信号量)的例子:

#include <QCoreApplication>

#include <QSemaphore>

#include <QDebug>

#include <QThread>

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

QSemaphore semaphore(1); // 初始信号量计数为1

// 创建两个线程,模拟同时访问共享资源

QThread thread1, thread2;

QObject::connect(&thread1, &QThread::started, [&]() {

semaphore.acquire();

qDebug() << "Thread 1: Accessing shared resource...";

QThread::sleep(2); // 模拟资源访问

semaphore.release();

qDebug() << "Thread 1: Done!";

});

QObject::connect(&thread2, &QThread::started, [&]() {

semaphore.acquire();

qDebug() << "Thread 2: Accessing shared resource...";

QThread::sleep(2); // 模拟资源访问

semaphore.release();

qDebug() << "Thread 2: Done!";

});

thread1.start();

thread2.start();

thread1.wait();

thread2.wait();

return a.exec();

}

5.QWaitCondition(条件变量)的例子:

#include <QCoreApplication>

#include <QMutex>

#include <QWaitCondition>

#include <QDebug>

#include <QThread>

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

QMutex mutex;

QWaitCondition condition;

bool isReady = false;

// 等待线程

QThread waitThread;

QObject::connect(&waitThread, &QThread::started, [&]() {

QMutexLocker locker(&mutex);

qDebug() << "Waiting thread: Waiting for condition...";

condition.wait(&mutex);

qDebug() << "Waiting thread: Condition signaled!";

});

// 发送信号线程

QThread signalThread;

QObject::connect(&signalThread, &QThread::started, [&]() {

QThread::sleep(2);

QMutexLocker locker(&mutex);

isReady = true;

qDebug() << "Signaling thread: Condition is ready!";

condition.wakeOne();

});

waitThread.start();

signalThread.start();

waitThread.wait();

signalThread.wait();

return a.exec();

}

三.其他线程同步机制

1.QThread::wait()

QThread::wait() 是Qt提供的一个线程同步机制,可以用于等待一个线程完成执行。调用该函数会使当前线程阻塞,直到指定的线程完成执行为止。

以下是一个使用QThread::wait()的示例:

#include <QThread>

#include <QDebug>

class Thread : public QThread

{

public:

void run() override

{

qDebug() << "Thread started";

sleep(1);

qDebug() << "Thread finished";

}

};

int main(int argc, char *argv[])

{

Thread thread;

thread.start();

qDebug() << "Waiting for thread to finish...";

thread.wait();

qDebug() << "Thread finished, exiting...";

}

在这个示例中,我们创建了一个Thread线程,并调用start()函数启动它。然后,我们调用QThread::wait()函数等待该线程完成执行。该函数会使当前线程阻塞,直到指定的线程完成执行为止。

相关推荐
cyt涛26 分钟前
MyBatis 学习总结
数据库·sql·学习·mysql·mybatis·jdbc·lombok
Rookie也要加油1 小时前
01_SQLite
数据库·sqlite
liuxin334455661 小时前
教育技术革新:SpringBoot在线教育系统开发
数据库·spring boot·后端
看山还是山,看水还是。2 小时前
MySQL 管理
数据库·笔记·mysql·adb
fishmemory7sec2 小时前
Koa2项目实战2(路由管理、项目结构优化)
数据库·mongodb·koa
momo小菜pa2 小时前
【MySQL 09】表的内外连接
数据库·mysql
Jasonakeke2 小时前
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化
数据库·mysql
程序猿小D2 小时前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
小宇成长录3 小时前
Mysql:数据库和表增删查改基本语句
数据库·mysql·数据库备份
团儿.3 小时前
解锁MySQL高可用新境界:深入探索MHA架构的无限魅力与实战部署
数据库·mysql·架构·mysql之mha架构