gpt4 book ai didi

c++ - 线程安全队列和虚假唤醒

转载 作者:行者123 更新时间:2023-11-28 01:42:39 27 4
gpt4 key购买 nike

我目前正在阅读一本关于 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 中的一些(可能的)等待线程可以恢复工作。在这种情况下,让我感到困惑的是虚假唤醒。如果在通知一个线程的同时另一个线程刚好同时醒来怎么办?当然他也看到了一个非空队列。在这种情况下,两个不同的线程会尝试弹出一个值,其中可能只有一个值存在 - 一种经典的竞争条件。

我在这里错过了什么吗?有一个更好的方法吗?

最佳答案

虚假唤醒只是意味着您需要检查唤醒条件在您被唤醒时是否仍然有效。由于 wait 函数被传递:

  1. 一个锁,用于互斥,以及
  2. 判断等待是否满足的谓词

当一个线程被“正常”通知而另一个线程被虚假通知时的行为是其中一个(无关紧要,以更快的速度为准)获取锁并确认队列非空,然后弹出顶部元素并释放锁;在较快的线程释放锁之前,失去锁竞争的线程不会获得锁,因此它看到已经清空的队列并确定这是虚假唤醒,然后返回 sleep 。

重要的是,虚假唤醒的线程是否赢得了锁(和排队的项目)的竞争并不重要;其中一个线程表现得好像被正常唤醒(它发现条件为真并按预期工作),一个好像被虚假唤醒(它发现条件为假并返回等待,如预期的那样),并且代码作为一个整体表现正确.

关于c++ - 线程安全队列和虚假唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46536018/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com