#线程同步
在前面理解了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; // 创建线程对象1MyThread thread2; // 创建线程对象2MyThread thread3; // 创建线程对象3thread1.start(); // 启动线程1thread2.start(); // 启动线程2thread3.start(); // 启动线程3thread1.wait(); // 等待线程1结束thread2.wait(); // 等待线程2结束thread3.wait(); // 等待线程3结束qDebug()<<"all thread quit.";return a.exec(); // 执行应用程序事件循环
}