Qt 线程(一) Qt 线程(一) Qt 多线程实现的两种方式 线程实现详解_恋恋西风的博客-CSDN博客_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);
- ..............
- }