我实现了一个简单的Producer-Consumer消息队列。
#include <chrono>
#include <iostream>
#include <thread>
#include <mutex>
#include <deque>
#define MESSAGE_QUIT 1
struct MessageQueue
{
std::deque<int> message_ids;
std::mutex mutex;
std::condition_variable condition_variable;
};
void SleepFor(int time_in_millis)
{
std::this_thread::sleep_for(std::chrono::milliseconds(time_in_millis));
}
void ProcessMessage(int message_id)
{
std::cout << "Processing Message #" << message_id << '\n';
}
void Producer(MessageQueue *messages)
{
for (int message_id = 10; message_id >= MESSAGE_QUIT; --message_id) {
std::unique_lock<std::mutex> guard(messages->mutex);
messages->message_ids.push_back(message_id);
guard.unlock();
messages->condition_variable.notify_one();
SleepFor(200);
}
}
void Consumer(MessageQueue *messages)
{
int next_message_id = -1;
while (next_message_id != MESSAGE_QUIT) {
std::unique_lock<std::mutex> guard(messages->mutex);
messages->condition_variable.wait(guard);
next_message_id = messages->message_ids.front();
messages->message_ids.pop_front();
guard.unlock();
ProcessMessage(next_message_id);
}
}
int main()
{
MessageQueue messages;
std::thread producer_thread(&Producer, &messages);
std::thread consumer_thread(&Consumer, &messages);
producer_thread.join();
consumer_thread.join();
}
竞争条件:在某些情况下,条件变量在生产者线程中调用notify_one()
,而它在消费者线程中不处于等待状态。你怎么解决这个问题?我现在不考虑虚假醒来的情况。
答案 0 :(得分:2)
条件变量可以虚假地唤醒。
messages->condition_variable.wait(guard)
所以不要这样做。还有其他原因不这样做,包括当数据准备就绪时你可以等待一个条件变量。
messages->condition_variable.wait(guard, [&]{return !messages->message_ids().empty();)
如果队列中已有消息,则不会等待。它还处理虚假的唤醒。