我有一个生产者 - 消费者多线程交互的实现。它工作。但我觉得在执行期间等待状态在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);
}
}
}
答案 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
,这可能会阻止生产者将项目推入队列,最终导致生命周期。