Qt::线程同步

1 QMutex(互斥锁)

  • 保护共享资源:多个线程尝试同时修改同一个数据时,使用QMutex保证一次只有一个线程能够修改。
  • 避免竞态条件:指的是两个或者更多的线程可以访问共享数据并且尝试改变它,这时候就会出现问题。互斥锁保证任何时候只有一个线程能够进入代码需要保护的部分。
  • 保证数据一致性:避免出现A正在写入数据而B也在尝试写入数据的情况。
  • 提高并发率:虽然互斥锁会引入一定量的开销,但是间接的提高了程序的整体性能。
  1. lock():锁定互斥量,如果另外一个线程锁定这个互斥量,它将阻塞执行指导线程解锁这个互斥量。
  2. unlock():解锁一个互斥量,需要和lock()配对使用。
  3. 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()解锁;
  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值