对生产者和消费者问题的另一个解决办法是使用QWaitCondition(封装好了wakeOne,wakeAll,而且与QReadWriteLock对接,几乎是万能的办法)

对生产者和消费者问题的另一个解决办法是使用QWaitCondition,它允许线程在一定条件下唤醒其他线程。其中wakeOne()函数在条件满足时随机唤醒一个等待线程,而wakeAll()函数则在条件满足时唤醒所有等待线程。

 

1、bool wait (QMutex * mutex,unsigned long time = ULONG_MAX)
1) 释放锁定的mutex
 2) 在线程对象上等待

         mutex必须由调用线程进行初锁定 。注意调用wait的话,会自动调用unlock解锁之前锁住的资源,不然会造成死锁。线程1等待线程2来改变共享资源,从而达到一定的条件然后发出信号,使得线程1从wait中的阻塞状态中被唤醒。但是线程2想改变资源,却无法办到,因为线程1调用lock之后就在wait中blocking,了但是没有及时的unlock,那么这就构成了死锁的条件。所以说wait函数除了使调用线程切换到内核态之外,还自动unlock(&mutex)。

2、void wakeOne ()
      这将会唤醒所有等待QWaitCondition的线程。这些线程被唤醒的顺序依赖于操组系统的调度策略,并且不能被控制或预知。

3、void wakeAll ()

       这将会唤醒所有等待QWaitCondition的线程中的一个线程。这个被唤醒的线程依赖于操组系统的调度策略,并且不能被控制或预知。

  下面通过一个典型用例:生产者和消费者,来实现这二者之间的同步。整个工程就一个main.cpp,文件如下:

复制代码
#include <QtCore/QCoreApplication>
#include <QWaitCondition>
#include <QThread>
#include <QMutex>
#include <iostream>

const int DataSize = 100;
const int BufferSize = 1;
char buffer[BufferSize];

QWaitCondition bufferIsNotFull;
QWaitCondition bufferIsNotEmpty;
QMutex mutex;
int usedSpace  = 0;

class Producer : public QThread
{
protected:
    void run()
    {
        for (int i = 0; i < DataSize; ++i)
        {
            mutex.lock();
            while (usedSpace == BufferSize)
            {
                bufferIsNotFull.wait(&mutex);
            }
            std::cerr<<"P";
            ++usedSpace;
            bufferIsNotEmpty.wakeAll();
            mutex.unlock();
        }
    }
};

class Consumer : public QThread
{
protected:
    void run()
    {
        for (int i = 0; i < DataSize; ++i)
        {
            mutex.lock();
            while (usedSpace == 0)
            {
                bufferIsNotEmpty.wait(&mutex);
            }
            std::cerr<<"C";
            --usedSpace;
            bufferIsNotFull.wakeAll();
            mutex.unlock();
        }
        std::cerr<<std::endl;
    }
};

int main(int argc, char *argv[])
{
   Producer producer;
   Consumer consumer;
   producer.start();
   consumer.start();
   producer.wait();
   consumer.wait();
return 0;
}

https://blog.csdn.net/skc361/article/details/19409527
posted @ 2018-05-24 22:41  findumars  Views(1652)  Comments(0Edit  收藏  举报