小蚂蚁 发表于 2021-12-17 18:17:52

条件变量QWaitCondition

条件变量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;    /*数据*/
    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 = 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++;
    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...
结束生产者!


https://blog.51cto.com/u_15462381/4811765
页: [1]
查看完整版本: 条件变量QWaitCondition