我目前正在阅读一本关于 C++ 中的多线程的书。在一章中,我找到了一些线程安全队列的源代码。它大致是这样构建的:
template<typename T>
class QueueThreadSafe
{
private:
std::mutex m_mutex;
std::queue<T> m_dataQueue;
std::condition_variable m_dataCondition;
public:
void push(T someValue)
{
std::lock_guard<std::mutex> guard(m_mutex);
m_dataQueue.push(someValue);
m_dataCondition.notify_one();
}
void pop(T &retVal)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_dataCondition.wait(lock, [this]{return !m_dataQueue.empty();});
retVal = m_dataQueue.front();
m_dataQueue.pop();
}
};
当一个值被推入队列时,会通知数据条件,并且 pop 中的一些(可能)等待线程可以恢复工作。在这种情况下,让我感到困惑的是虚假的唤醒。如果在通知一个线程的同时,另一个线程同时唤醒了怎么办?当然,他也看到了一个非空队列。在这种情况下,两个不同的线程会尝试弹出一个值,其中可能只存在一个值 - 一个经典的竞争条件。
我在这里错过了什么吗?有一个更好的方法吗?