0
点赞
收藏
分享

微信扫一扫

Qt 线程(二) Qt 线程常用同步方式


Qt  线程(一) ​​Qt 线程(一) Qt 多线程实现的两种方式 线

多个线程同时访问共享数据时可能会冲突,出现意料之外的结果,这源于操作的原子性问题;为了保证,数据的正确性和完成性,就需要用到数据同步,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);
..............
}

举报

相关推荐

0 条评论