当前位置:网站首页>Qt 线程常用同步方式
Qt 线程常用同步方式
2022-08-10 03:26:00 【恋恋西风】
多个线程同时访问共享数据时可能会冲突,出现意料之外的结果,这源于操作的原子性问题;为了保证,数据的正确性和完成性,就需要用到数据同步,Qt给我们提供了多种同步方式,
下面说一下主要方式:
互斥锁 | QMute |
条件变量 | QWaitCondition |
信号量 | QSemaphore |
读写锁 | QReadLocker、QWriteLocker、QReadWriteLock |
1. 互斥量 QMutex
我们一般使用 QMutexLocker 对于当前的范围,进行锁住,当离开范围时,自动解锁。
值得注意的是,需要在两个线程中使用同一个锁,然后才能起到锁的作用,主要是为了防止多线程对单个数据的同时操作。 在单线程中,对于锁而言,是没有任何意义的。
mythread.cpp
QMutex mWaitMutex;
void MyThread::run()
{
exitflag = true;
while(exitflag)
{
QMutexLocker locker(&mWaitMutex);
qDebug() << "MyThread thread id:" << QThread::currentThreadId();
sleep(1);
}
}
2. 条件变量QWaitCondition
注意这个要和 QMutex 一起配合使用;
使用场景:线程A需要等某个条件成立才能继续往下执行,比如 生产者,消费者
void MyThread::run()
{
exitflag = true;
while(exitflag)
{
QMutexLocker locker(&mWaitMutex);
mWaitStatusCondition.wait(&mWaitMutex,1);
qDebug() << "MyThread thread id:" << QThread::currentThreadId();
sleep(1);
}
}
void MyThread::stop()
{
mWaitStatusCondition.wakeAll();
}
3. 信号量semaphore
这是一种提供计数的信号量,所以在消费者与生产者模型中,就变得十分的好用。如果缓存被消费者还没有读取的数据填满,acquire()的调用就会阻塞,直到消费者已经开始消耗这些数据;
API:
(1)获取n个资源
调用acquire(n)将尝试获取n个资源。如果没有那么多可用的资源,调用将被阻塞,直到出现可用的资源为止。
void QSemaphore::acquire(int n = 1)
(2)释放n个资源
调用release(n)函数释放n个资源。
void QSemaphore::release(int n = 1)
(3)获取可用资源的数量
调用available()函数返回可用资源的数量。
int QSemaphore::available() const
(4)尝试获取n个资源
调用tryAcquire()函数尝试获取资源,如果不能获取资源,它将立即返回。
bool QSemaphore::tryAcquire(int n = 1)
使用样例:
const int BufferSize = 12;
QSemaphore freeBytes(BufferSize);
QSemaphore usedBytes;
const int DataSize = 100;
class Producer : public QThread
{
public:
void run() override
{
for (int i = 0; i < DataSize; ++i) {
freeBytes.acquire();
// doing produce
usedBytes.release();
}
}
};
class Consumer : public QThread
{
Q_OBJECT
public:
void run() override
{
for (int i = 0; i < DataSize; ++i) {
usedBytes.acquire();
// doing consume;
freeBytes.release();
}
fprintf(stderr, "\n");
}
};
main
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Producer producer;
Consumer consumer;
producer.start();
consumer.start();
producer.wait();
consumer.wait();
return 0;
}
4. 读写锁
前两种保护互斥量的方法比较绝对,其达到的效果是:不管我要对互斥量做些是什么,我都要一个人霸占着,即使我只是看看它,也不能让别人看。这会使得这个互斥量资源的使用率大大下降,造成资源等待等问题。
void write()
{
QReadLocker locker(&lock);
..........
}
void read()
{
QWriteLocker locker(&lock);
..............
}
边栏推荐
猜你喜欢
随机推荐
BFF避坑指南
有关视频传输时粘包问题的一些解决方法
Do you know these basic types of software testing?
flutter 每天一背,需要掌握
如何使用腾讯字体,已经在什么场合下可以使用该字体?TTTGB-Medium
leetcode 283:移动零
Mini Program Navigation and Navigation Parameters
Classes and interfaces
fastjson autoType is not support
How does a new tester do functional testing?Test thinking is really important
【2022河南萌新联赛第(五)场:信息工程大学】【部分思路题解+代码解析】
Did not detect default resource location for test class xxxx
Take you to an in-depth understanding of the version update of 3.4.2, what does it bring to users?
program internationalization
互联网公司高频面试题精讲:测试计划和测试方案有什么区别?
软件的生命周期(软件工程各阶段的工作)
请教各位confluence部署连接数据库成功,但是在后面建表设置的时候报错
flutter异步
ThreedLocal在单线程中的应用【获取在拦截器中登录的用户信息】
如何快速成为一名软件测试工程师?测试员月薪15k需要什么技术?