当前位置:网站首页>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);
..............
}边栏推荐
- exchange2010 邮件数据库无法装入
- leetcode-218.天际线问题
- 【IO复用】poll
- 如何快速成为一名软件测试工程师?测试员月薪15k需要什么技术?
- 请教各位confluence部署连接数据库成功,但是在后面建表设置的时候报错
- uva1392
- BFF避坑指南
- 如何整合全流程数据,全面提升研发效能?|2分钟了解 ONES
- Software life cycle (the work of each phase of software engineering)
- How does a new tester do functional testing?Test thinking is really important
猜你喜欢
随机推荐
线程和线程间通信(C语言)
ARP欺骗-教程详解
js原型和原型链以及原型继承
学习总结week4_2正则
新零售社交电商APP系统平台如何打造公域+私域流量?
三极管开关电路参数设计与参数介绍
从零开始配置 vim(9)——初始配置
plsql 查询数据库操作历史记录(Ctrl + e)
matlab simulink response spectrum calculation
超全面的Android面试题汇总
(十四)时间延时任务及定时任务
electron 应用开发优秀实践
Difference between netstat and ss command
如何使用腾讯字体,已经在什么场合下可以使用该字体?TTTGB-Medium
二进制与内存
《天才基本法》:平行时空的第二次选择,小演员的表现意外出圈
vue项目 npm run build 打包项目防止浏览器缓存
Basic understanding of network models
Embedded Sharing Collection 32
Flink学习15:Flink自定义数据源









