我遇到了僵局,无法用下面的代码解释。由于“虚假唤醒”,我预计代码应该可以工作,但我认为我遗漏了一些东西。我检查了这个条件变量死锁但没有运气。
class SafeQueue
{
private:
std::queue<int> data_queue;
mutable std::mutex m;
std::condition_variable cv;
std::atomic<bool> flag{ true }; // Atomic flag to control the queue
public:
void push(int val)
{
std::lock_guard<std::mutex> lock(m);
data_queue.push(val);
cv.notify_one(); // Notify waiting thread upon pushing data
}
bool pop(int& val)
{
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [this]() { return !data_queue.empty() || !flag; }); // Wait until queue is not empty or flag is turned off
if (!flag && data_queue.empty())
{
return false; // Queue is empty and flag is off, return false to indicate termination
}
if (!data_queue.empty())
{
val = data_queue.front();
data_queue.pop();
return true;
}
return false;
}
void turnOff()
{
flag = false;
}
bool isFlagOn() const
{
return flag;
}
};
void consumerLoop(SafeQueue& q)
{
while (q.isFlagOn())
{
int val;
if (q.pop(val))
{
std::cout << "Consumed: " << val << std::endl;
}
}
std::cout << "Consumer exiting" << std::endl;
}
int main()
{
SafeQueue q;
std::thread consumerThread(consumerLoop, std::ref(q));
// Producer pushes some values into the queue
for (int i = 0; i < 10; ++i)
{
q.push(i);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// Turn off the queue flag
q.turnOff();
consumerThread.join();
return 0;
}
您能帮忙指出发生在哪里以及如何纠正实施吗?欢迎任何其他实施建议(我需要一个双端队列
为了简单起见,我只是包含了队列的示例)
consumerThread
挂在
cv.wait
上,并且仅当 push
执行 cv.notify_one()
时才会醒来。这种情况发生 10 次,然后生产者循环完成,并且 flag
被关闭 - 然而 consumerThread
仍然/再次挂在 cv.wait
上。此时,您的 consumerThread
会卡住,直到:
有人打电话给cv.notify_one()
cv.notify_all()
)您会得到虚假唤醒 - 但请记住,这些大多是您“可能”从各种现实世界条件中获得的缺陷(这就是为什么您需要像它们可能发生一样进行编码),但它们“不”是假设的发生。void turnOff()
{
flag = false;
cv.notify_one();
}