当前位置:网站首页>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);
..............
}
边栏推荐
猜你喜欢
新零售社交电商APP系统平台如何打造公域+私域流量?
【Image Classification】2022-CycleMLP ICLR
三极管开关电路参数设计与参数介绍
The so-called software testing ability is actually these 5 points
如何让导电滑环信号更好
Shell 文本三剑客 awk
Did not detect default resource location for test class xxxx
实测办公场景下,国产远程控制软件的表现力如何?(技术解析)
Dynamic Web Development Fundamentals
NFG电商系统在元宇宙趋势下做什么?
随机推荐
flutter异步
Evaluation and Construction of Enterprise Network Security Capability from the Sliding Ruler Model
从8k到13k,我全靠这本《接口自动化测试——从入门到精通》
plsql 查询数据库操作历史记录(Ctrl + e)
ES高亮显示语法
二维空间下的向量旋转
第三章 搜索与图论(二)
如何使用腾讯字体,已经在什么场合下可以使用该字体?TTTGB-Medium
金融财经翻译的行业前景如何
如何让导电滑环信号更好
Camera partial update
动态网页开发基础
...spread、命名空间、假报错、变化事件、async/await
mediaserver创建
小程序分包及分包预下载
shell文本编辑awk
@Autowired注解 --required a single bean, but 2 were found出现的原因以及解决方法
goland控制台显示重叠问题解决方案
电话自动拨号在电脑上自动拨打
【Image Classification】2022-CycleMLP ICLR