1 QMutex(互斥锁)
- 保护共享资源:多个线程尝试同时修改同一个数据时,使用QMutex保证一次只有一个线程能够修改。
- 避免竞态条件:指的是两个或者更多的线程可以访问共享数据并且尝试改变它,这时候就会出现问题。互斥锁保证任何时候只有一个线程能够进入代码需要保护的部分。
- 保证数据一致性:避免出现A正在写入数据而B也在尝试写入数据的情况。
- 提高并发率:虽然互斥锁会引入一定量的开销,但是间接的提高了程序的整体性能。
- lock():锁定互斥量,如果另外一个线程锁定这个互斥量,它将阻塞执行指导线程解锁这个互斥量。
- unlock():解锁一个互斥量,需要和lock()配对使用。
- tryLock():试图锁定一个互斥量,如果成功锁定返回true,如果其他线程已经锁定这个互斥量则返回false,但不会阻塞程序执行。
#pragma once
#include <QObject>
#include <QThread>
#include <QMutex>
#include <QTimer>
#include <QTime>
#include <QDebug>
class QThreadTest2 : public QThread
{
Q_OBJECT
public:
QThreadTest2(QObject* parent = nullptr);
~QThreadTest2();
private:
QMutex m_mutex;
int m_seq = 0;
int m_diceValue;
protected:
virtual void run() override;
public:
void readValue(int* req, int* dicValue);
};
#include "QThreadTest2.h"
QThreadTest2::QThreadTest2(QObject* parent /*= nullptr*/)
{
}
QThreadTest2::~QThreadTest2()
{
}
void QThreadTest2::run()
{
qsrand(QTime::currentTime().msec());
while (true)
{
m_mutex.lock();
m_diceValue = qrand();
m_diceValue = (m_diceValue % 6) + 1;
m_seq++;
m_mutex.unlock();
msleep(100);
}
}
void QThreadTest2::readValue(int* req, int* dicValue)
{
if (m_mutex.tryLock())
{
*req = m_seq;
*dicValue = m_diceValue;
m_mutex.unlock();
qDebug() << *req << " " << *dicValue;
}
else
{
qDebug() << u8"解锁失败";
}
}
进行调用:
QThreadTest2* m_QThreadTest2;
QTimer* m_timer;
int req;
int devicValue;
private slots:
void timeOut();
########################
m_QThreadTest2 = new QThreadTest2;
m_QThreadTest2->start();
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(timeOut()));
m_timer->start(50);
########################
void QtWidgetsApplication1::timeOut()
{
m_QThreadTest2->readValue(&req, &devicValue);
}
2 QMutexLocker
QMutexLocker是一个简化了QMutex的类,确保在进入作用域自动获取锁,退出作用域释放锁,避免竞态条件。如 1 中的程序可以修改为:
#include "QThreadTest2.h"
QThreadTest2::QThreadTest2(QObject* parent /*= nullptr*/)
{
}
QThreadTest2::~QThreadTest2()
{
}
void QThreadTest2::run()
{
qsrand(QTime::currentTime().msec());
while (true)
{
//m_mutex.lock();
QMutexLocker locker(&m_mutex);
m_diceValue = qrand();
m_diceValue = (m_diceValue % 6) + 1;
m_seq++;
//m_mutex.unlock();
msleep(100);
}
}
void QThreadTest2::readValue(int* req, int* dicValue)
{
//if (m_mutex.tryLock())
//{
// *req = m_seq;
// *dicValue = m_diceValue;
// m_mutex.unlock();
// qDebug() << *req << " " << *dicValue;
//}
//else
//{
// qDebug() << u8"解锁失败";
//}
* req = m_seq;
*dicValue = m_diceValue;
qDebug() << *req << " " << *dicValue;
}
3 QReadWriteLock
QReadWriteLock提供以下几个主要函数:
- lockForRead():以只读的方式锁定资源,如果存在其他线程有写入方式锁定,这个函数会阻塞。
- lockForWrite():以写入的方式锁定资源,如果本线程或者其他线程以读或者写的方式锁定资源,这个函数就会阻塞。
- unlock()解锁;