QWaitCondition类所表示的等待条件,可以与QMutex类所表示的互斥体结合使用,在执行操作的条件不满足时,陷入睡眠,同时解锁所持有的互斥体,以使其它线程得以执行为其创造条件的操作,待条件满足时再被唤醒,重新锁定互斥体后,执行那些有赖于该条件的操作。
xxxxxxxxxx
41bool QWaitCondition::wait(QMutex* lockedMutex, // 陷入睡眠,同时解锁lockedMutex,
2 unsigned long time = ULONG_MAX); // 被唤醒后,重新锁定lockedMutex,并返回
3void QWaitCondition::wakeAll(); // 唤醒所有在该等待条件中睡眠的线程,但只有一个线程能成功锁定互斥体,并从wait中返回
4void QWaitCondition::wakeOne(); // 唤醒一个在该等待条件中睡眠的线程,该线程在重新锁定互斥体后从wait调用中返回
生产者负责生产数据,消费者负责消费数据,二者共享同一个数据缓冲区。
通过QtCreator,在C:\Users\Minwei\Projects\Qt路径下,创建名为WaitCondition的控制台(Console)项目。
C:\Users\Minwei\Projects\Qt\WaitCondition\main.cpp:
xxxxxxxxxx
1171
2using namespace std;
3
4
5
6
7
8
9
10
11
12char g_storage[MAX_STOCK];
13size_t g_stock = 0;
14
15QMutex g_mutex;
16QWaitCondition g_nonFull;
17QWaitCondition g_nonEmpty;
18
19void show (char const* name, char const* op, char prod) {
20 cout << name << "> ";
21
22 for (size_t i = 0; i < g_stock; ++i)
23 cout << g_storage[i];
24
25 cout << op << prod << endl;
26}
27
28class Producer: public QThread {
29public:
30 Producer(char const* name)
31 : m_name(name)
32 , m_speed(time(NULL))
33 , m_prod(time(NULL))
34 {
35 }
36
37protected:
38 void run()
39 {
40 for (;;)
41 {
42 g_mutex.lock();
43
44 while (g_stock >= MAX_STOCK)
45 {
46 cout << m_name << "> FULL!" << endl;
47 g_nonFull.wait(&g_mutex);
48 }
49
50 char prod = m_prod.bounded('A', 'Z' + 1);
51 show(m_name, "<-", prod);
52 g_storage[g_stock++] = prod;
53
54 g_nonEmpty.wakeAll();
55
56 g_mutex.unlock();
57
58 msleep(m_speed.bounded(1, 101));
59 }
60 }
61
62private:
63 char const* m_name;
64 QRandomGenerator m_speed, m_prod;
65};
66
67class Consumer: public QThread {
68public:
69 Consumer(char const* name)
70 : m_name(name)
71 , m_speed(time(NULL))
72 {
73 }
74
75protected:
76 void run()
77 {
78 for (;;)
79 {
80 g_mutex.lock();
81
82 while (!g_stock)
83 {
84 cout << m_name << "> EMPTY!" << endl;
85 g_nonEmpty.wait(&g_mutex);
86 }
87
88 char prod = g_storage[--g_stock];
89 show(m_name, "->", prod);
90
91 g_nonFull.wakeAll();
92
93 g_mutex.unlock();
94
95 msleep(m_speed.bounded(1, 101));
96 }
97 }
98
99private:
100 char const* m_name;
101 QRandomGenerator m_speed;
102};
103
104int main(int argc, char *argv[])
105{
106 QCoreApplication a(argc, argv);
107
108 Producer p1("PRODUCER-1"), p2("PRODUCER-2");
109 p1.start();
110 p2.start();
111
112 Consumer c1("CONSUMER-1"), c2("CONSUMER-2");
113 c1.start();
114 c2.start();
115
116 return a.exec();
117}
运行效果如图所示:
xxxxxxxxxx
201PRODUCER-1> <-F
2PRODUCER-2> F<-F
3CONSUMER-1> F->F
4CONSUMER-2> ->F
5CONSUMER-2> EMPTY!
6CONSUMER-1> EMPTY!
7PRODUCER-2> <-A
8PRODUCER-1> A<-A
9...
10PRODUCER-1> ACIRMEVS<-D
11PRODUCER-2> ACIRMEVSD<-F
12CONSUMER-1> ACIRMEVSD->F
13PRODUCER-1> ACIRMEVSD<-T
14PRODUCER-2> FULL!
15CONSUMER-1> ACIRMEVSD->T
16PRODUCER-2> ACIRMEVSD<-F
17PRODUCER-1> FULL!
18CONSUMER-2> ACIRMEVSD->F
19PRODUCER-2> ACIRMEVSD<-V
20...