#线程同步
在前面理解了QThread两种使用方法,和线程机制以及退出过程后,需要了解线程同步的内容了,今天开启学习线程同步知识。
还是从大佬的文章开始。
从下面这篇文章开始学习
线程同步
线程同步有:
QMutex(互斥),QSemaphore(信号量),QWaitCondition,QReadWriteLock
QMutex 的基本功能是不允许同时访问同一个资源,对资源的同时访问进行排斥。使用系统的原子操作进行锁和开锁两种操作。
使用互斥,使得资源同一时间只有一个线程访问。当一个线程进行lock操作时,如果mutex是unlock状态,则lock成功,线程继续执行。如果mutex是lock状态,则尝试lock的线程在等待状态,等待另一个线程unlock。
线程同步文章中的例子是直接正确可以直接使用,这里贴出代码。
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QMutex>
// 定义共享资源
int sharedValue = 0;
QMutex mutex;
// 定义一个线程类
class MyThread : public QThread
{
public:
void run() override {
for(int i = 0; i < 5; i++) {
mutex.lock(); // 加锁
sharedValue++; // 访问共享资源
qDebug() << "Thread ID: " << QThread::currentThreadId() << " - Shared Value: " << sharedValue;
msleep(1000); // 线程休眠1秒
mutex.unlock(); // 解锁
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyThread thread1;
MyThread thread2;
thread1.start();
thread2.start();
thread1.wait();
thread2.wait();
qDebug() << "Final Shared Value: " << sharedValue;
return a.exec();
}
QSemaphore
QSemaphore 是 Qt 中用于实现信号量的类,用于控制对共享资源的访问数量。原文章提出“当信号量的值为正时,线程可以获得该信号量;当信号量的值为零时,线程将被阻塞,直到有线程释放信号量。”这里是再细分一下,线程可以不阻塞也可以阻塞,取决于使用方式
。
对代码稍作修改后如下:
如果阻塞方式,将等待,从而不会出现信号量没有活动的打印语句(Semaphore not acquired)
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QSemaphore>
QSemaphore semaphore(2); // 定义能够同时访问资源的线程数量为2的信号量
bool block = false;//是否阻塞方式
class MyThread : public QThread // 定义一个线程类
{
public:
void run() override {
if(semaphore.tryAcquire(1,block?-1:1)) { // 尝试获取信号量
qDebug() << "Thread ID: " << QThread::currentThreadId() << " - Acquired Semaphore"; // 输出线程ID和已获取信号量消息
sleep(2); // 线程休眠2秒
qDebug() << "Thread ID: " << QThread::currentThreadId() << " - Releasing Semaphore"; // 输出线程ID和释放信号量消息
semaphore.release(); // 释放信号量
} else {
qDebug() << "Thread ID: " << QThread::currentThreadId() << " - Semaphore not acquired"; // 输出线程ID和未获取信号量消息
}
qDebug()<<QThread::currentThreadId()<<"thread exit.";
}
};
int main(int argc, char *argv[]) // 主函数
{
QCoreApplication a(argc, argv); // 创建应用程序对象
MyThread thread1; // 创建线程对象1
MyThread thread2; // 创建线程对象2
MyThread thread3; // 创建线程对象3
thread1.start(); // 启动线程1
thread2.start(); // 启动线程2
thread3.start(); // 启动线程3
thread1.wait(); // 等待线程1结束
thread2.wait(); // 等待线程2结束
thread3.wait(); // 等待线程3结束
qDebug()<<"all thread quit.";
return a.exec(); // 执行应用程序事件循环
}