0. 参考文献
1. 简述
QWaitCondition
是用来同步线程的条件变量,头文件#include <QWaitCondition>
,类中的所有函数都是线程安全的。主要的公共函数如下表:
返回类型 | 函数名 |
---|---|
QWaitCondition () | |
~QWaitCondition () | |
bool | wait ( QMutex * mutex, unsigned long time = ULONG_MAX ) |
bool | wait ( QReadWriteLock * readWriteLock, unsigned long time = ULONG_MAX ) |
void | wakeAll () |
void | wakeOne () |
该类允许一个线程来告诉其他线程一些种情况已经被遇到。一个或者多个线程能阻塞等待为一个QWaitCondition来设置一个情况用wakeOne()或wakeAll()。使用wakeOne()来随机唤醒一个被选择的情况或者wakeAll()来唤醒所有的。
2. 生产消费者模型
文章 Qt - 生产者和消费者模型示例中介绍了两种实现方法,本文只摘录用QWaitCondition
实现的方法。如下所示:
1 #ifndef MUTEXWAITCONDITION
2 #define MUTEXWAITCONDITION
3
4 #include <QCoreApplication>
5 #include <iostream>
6 #include <QThread>
7 #include <QMutex>
8 #include <QWaitCondition>
9
10 using namespace std;
11
12 class MutexWaitCondition {
13 public:
14 //预计生产(或消费)数量
15 int loopCount;
16 //当前产品数量
17 int product;
18 //仓库能容纳的最大产品数量
19 int capacity;
20
21 QMutex mutex;
22 /*
23 The QWaitCondition class provides a condition variable for synchronizing threads
24 QWaitCondition类为线程同步提供了一个条件变量
25 */
26 QWaitCondition productIsNotFull;
27 QWaitCondition productIsNotEmpty;
28
29 //生产者
30 class Producer : public QThread {
31 public:
32 Producer(MutexWaitCondition *manager) : QThread() {
33 this->manager = manager;
34 }
35 protected:
36 void run() {
37 for(int i=0; i<manager->loopCount; i++) {
38 manager->mutex.lock();
39 while(manager->product == manager->capacity) {
40 /*
41 bool QWaitCondition::wait(QReadWriteLock * lockedReadWriteLock, unsigned long time = ULONG_MAX)
42 Releases the lockedReadWriteLock and waits on the wait condition
43 释放该锁,并且阻塞当前线程,直到条件满足(即调用wake方法被唤醒)
44 */
45 manager->productIsNotFull.wait(&manager->mutex);
46 }
47 manager->product++; //当前产品数量++之前产品就要入队
48 //cout<<"P";
49 cout<<i<<".P="<<manager->product<<", ";
50 manager->productIsNotEmpty.wakeAll();
51 manager->mutex.unlock();
52 }
53 }
54 private:
55 MutexWaitCondition *manager;
56 };
57
58 //消费者
59 class Consumer : public QThread {
60 public:
61 Consumer(MutexWaitCondition *manager) : QThread() {
62 this->manager = manager;
63 }
64 protected:
65 void run() {
66 for(int i=0; i<manager->loopCount; i++) {
67 manager->mutex.lock();
68 while(manager->product == 0) {
69 manager->productIsNotEmpty.wait(&manager->mutex);
70 }
71 manager->product--; //当前产品数量--之前产品就要出队
72 //cout<<"C";
73 cout<<i<<".C="<<manager->product<<", ";
74 manager->productIsNotFull.wakeAll();
75 manager->mutex.unlock();
76 }
77 }
78 private:
79 MutexWaitCondition *manager;
80 };
81
82 //无修饰的方法,默认是private的
83 public:
84 void test(int loopCount, int capacity)
85 {
86 this->loopCount = loopCount;
87 this->capacity = capacity;
88 this->product = 0;
89
90 Producer producer(this);
91 Consumer consumer(this);
92 //thread.start会调用thread内部的run方法
93 producer.start();
94 consumer.start();
95 /*
96 Blocks the thread until either of these conditions is met:
97 阻塞该线程直到所有条件都满足
98 */
99 producer.wait();
100 consumer.wait();
101 cout<<endl;
102 }
103 };
104 #endif // MUTEXWAITCONDITION
3. 如何退出生产消费者模型?
文章多线程生产者、消费者模式中,如何停止消费者中给出了退出的思路,即“毒丸计划”,其实就是在生产队列里放入一个残次品作为终止生产和消费的标识。