评论

收藏

[C++] 条件变量QWaitCondition

编程语言 编程语言 发布于:2021-12-17 18:17 | 阅读数:410 | 评论:0

条件变量QWaitCondition
Qt里面叫等待条件,Linux下叫条件变量,我统一都称呼为条件变量
QWaitCondition 允许线程在某些情况发生时唤醒另外的线程。一个或多个线程可以阻塞等待​​QWaitCondition ​​,用​​wakeOne()​​或w​​akeAll()​​设置一个条件。​​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...
结束生产者!

关注下面的标签,发现更多相似文章