条件变量QWaitCondition
Qt里面叫等待条件,Linux下叫条件变量,我统一都称呼为条件变量
QWaitCondition 允许线程在某些情况发生时唤醒另外的线程。一个或多个线程可以阻塞等待QWaitCondition ,用wakeOne()或wakeAll()设置一个条件。wakeOne()随机唤醒一个,wakeAll()唤醒所有。QWaitCondition ()
bool wait ( QMutex * mutex, unsigned long time = ULONG_MAX )
bool wait ( QReadWriteLock * readWriteLock, unsigned long time = ULONG_MAX )
void wakeOne ()
void wakeAll ()
头文件声明: #include <QWaitCondition>
等待条件声明: QWaitCondtion m_WaitCondition;
等待条件等待: m_WaitConditon.wait(&m_muxtex, time);
等待条件唤醒: m_WaitCondition.wakeAll(); 在经典的生产者-消费者场合中,生产者首先必须检查缓冲是否已满,如果缓冲区已满,线程停下来等待 notfull条件。如果没有满,在缓冲中生产数据,激活条件 nottempty。使用mutex来保护对buffer的访问。QWaitCondition::wait() 接收一个mutex作为参数,mutex被调用线程初始化为锁定状态。在线程进入休眠状态之前,mutex会被解锁。而当线程被唤醒时,mutex会处于锁定状态,从锁定状态到等待状态的转换是原子操作。当程序开始运行时,只有生产者可以工作,消费者被阻塞等待nottempty条件,一旦生产者在缓冲中放入一个字节,nottempty条件被激发,消费者线程于是被唤醒。
生产者和消费者示例:#include <QtCore/QCoreApplication>
#include <QThread>
#include <QWaitCondition>
#include <QMutex>
#include <QDebug>
#define BUFFER_SIZE 2
/*生产者*/
class producons
{
public:
int buffer[BUFFER_SIZE]; /*数据*/
QMutex lock; //互斥锁
int readpos,writepos; //读写位置
QWaitCondition nottempty; //条件变量 没有空间
QWaitCondition notfull; //条件变量 没有货物
producons()
{
readpos = writepos = 0;
}
};
producons buffer; //生产者对象
class Producor:public QThread
{
public:
void run();
void put(producons * prod,int data);
};
void Producor::run()
{
int n;
for(n = 0;n<5;n++)
{
qDebug()<<"生产者睡眠 1s...";
sleep(1);
qDebug()<<"生产信息:" << n;
put(&buffer, n);
}
for(n=5; n<10; n++)
{
qDebug()<<"生产者睡眠 3s...";
sleep(3);
qDebug()<<"生产信息:"<< n;
put(&buffer,n);
}
put(&buffer, -1);
qDebug()<<"结束生产者!\n";
return;
}
void Producor::put(producons *prod, int data)
{
prod->lock.lock();
//write until buffer not full
while((prod->writepos + 1)%BUFFER_SIZE == prod->readpos)
{
qDebug()<<"生产者等待生产,直到buffer有空位置";
prod->notfull.wait(&prod->lock);
}
//将数据写入到buffer里面去
prod->buffer[prod->writepos] = data;
prod->writepos++;
if(prod->writepos >= BUFFER_SIZE)
prod->writepos = 0;
//仓库已满,等待消费者消费
prod->nottempty.wakeAll();
prod->lock.unlock();
}
class Consumer:public QThread
{
public:
void run();
int get(producons *prod);
};
void Consumer::run()
{
int d = 0;
while(1)
{
qDebug()<<"消费者睡眠 2s...";
sleep(2);
d = get(&buffer);
qDebug()<<"读取信息:"<< d;
if(d == -1) break;
}
qDebug()<<"结束消费者!";
return;
}
int Consumer::get(producons *prod)
{
int data;
prod->lock.lock(); //加锁
while(prod->writepos == prod->readpos)
{
qDebug()<<"消费者等待,直到buffer有消息\n";
prod->nottempty.wait(&prod->lock);
}
//读取buffer里面的消息
data = prod->buffer[prod->readpos];
prod->readpos++;
if(prod->readpos >=BUFFER_SIZE)
prod->readpos = 0;
//触发非满条件变量 告诉生产者可以生产
prod->notfull.wakeAll();
prod->lock.unlock();
return data;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Producor productor;
Consumer consumer;
productor.start();
consumer.start();
productor.wait();
consumer.wait();
return a.exec();
}
生产者睡眠 1s...
消费者睡眠 2s...
生产信息: 0
生产者睡眠 1s...
读取信息: 0
生产信息: 1
消费者睡眠 2s...
生产者睡眠 1s...
生产信息: 2
生产者等待生产,直到buffer有空位置
读取信息: 1
生产者睡眠 1s...
消费者睡眠 2s...
生产信息: 3
生产者等待生产,直到buffer有空位置
读取信息: 2
生产者睡眠 1s...
消费者睡眠 2s...
生产信息: 4
生产者等待生产,直到buffer有空位置
读取信息: 3
生产者睡眠 3s...
消费者睡眠 2s...
读取信息: 4
消费者睡眠 2s...
生产信息: 5
生产者睡眠 3s...
读取信息: 5
消费者睡眠 2s...
生产信息: 6
消费者等待,直到buffer有消息
生产者睡眠 3s...
读取信息: 6
消费者睡眠 2s...
消费者等待,直到buffer有消息
生产信息: 7
生产者睡眠 3s...
读取信息: 7
消费者睡眠 2s...
消费者等待,直到buffer有消息
生产信息: 8
生产者睡眠 3s...
读取信息: 8
消费者睡眠 2s...
消费者等待,直到buffer有消息
生产信息: 9
生产者等待生产,直到buffer有空位置
读取信息: 9
消费者睡眠 2s...
结束生产者!
|