优化Producer - Consumer线程之间的交互

时间:2014-08-14 09:03:33

标签: c++ multithreading boost

我有一个生产者 - 消费者多线程交互的实现。它工作。但我觉得在执行期间等待状态在Consumer线程和Producer之间经常发生。在我的情况下,Consumer以随机间隔访问队列并获取数据现在,生产者线程在整个生命周期中运行。生产者线程作为缓存机器工作。如果队列的大小小于允许的最大缓存大小,它会在循环中检查,如果这是它不断将新数据推送到该缓存中。我担心的是,当消费者试图访问队列时,最后一个仍被生产者线程锁定,消费者应该等待。理想情况下,我想让消费者导致生产者& #39;冻结'并且当消费者从队列中检索数据时立即解锁。

以下是我现在的表现:

   //Called by consumer(main thead) to retrieve data from cache
   uint8_t* Worker::GetFrame() {

      boost::unique_lock<boost::mutex> lk(_frameCacheMutex);
      //If the cache is empty:
      while (0 == _frames_cache.size()) {
               //tell Producer to push data into cache
             _fill_cache_wait_cond.notify_one();
              //wait for the data to arrive(will be signaled by worker thread)
             _get_frame_wait_cond.wait(lk);

      }
      uint8_t * fr = _frames_cache.front();
      _frames_cache.pop();
      // notify worker thread to continue caching
      _fill_cache_wait_cond.notify_one();

      return fr;
   }

制作人主题:

    void Worker::operator () () {
      //Some init here..
        while (isRunning) {
           boost::unique_lock<boost::mutex> lk(_frameCacheMutex);

           /// Here create the data for cache...

           _frames_cache.push(data);

           /// Notify waiting main thread to take data
           _get_frame_wait_cond.notify_one();

           /// If the cache is full ,wait
           while (_frames_cache.size() == cacheMaxSize ){

                 _fill_cache_wait_cond.wait(lk);

           }

        }     

    }

2 个答案:

答案 0 :(得分:1)

此时,生产者锁定队列直到它满了。只有在那时,消费者才能访问队列,但它立即发出队列不再满的信号,因此生产者再次锁定队列。

至少只有在数据准备好被推后才锁定,并尝试限制推送操作 如果可能的话,你也可以增加消费者的优先权。

顺便说一句,这不会解决您的问题,但您可以限制notify_one()次呼叫的数量,因为您只需在条件实际发生变化时发送一次(不再为零而不是消费者,而不是已经完全生产了。)

答案 1 :(得分:0)

std::atomic<bool> producerShouldSleep = false;
std::atomic<bool> producerIsSleeping = false;

Item consumeItem(){ //consumer
    producerShouldSleep = true;
    while (!producerIsSleeping)
        yield();
    auto item = getItemFromQueue();
    producerShouldSleep = false;
    return item;
}

void produceData(){ //producer
    while (shouldBeRunning){
        if (producerShouldSleep){
            producerIsSleeping = true;
            while (producerShouldSleep)
                yield();
            producerIsSleeping = false;
            continue;
        }
        if (!queueIsFull())
            pushItemIntoQueue();
    }
}

这将优先考虑消费者。除非我搞砸了什么,否则它将被正确同步。我看到的唯一问题是队列可能是空的,并且有人在紧密循环中调用consumeItem,这可能会阻止生产者将项目推入队列,最终导致生命周期。