条件变量死锁示例

问题描述 投票:0回答:1

我遇到了僵局,无法用下面的代码解释。由于“虚假唤醒”,我预计代码应该可以工作,但我认为我遗漏了一些东西。我检查了这个条件变量死锁但没有运气。 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; }

您能帮忙指出发生在哪里以及如何纠正实施吗?欢迎任何其他实施建议(
我需要一个双端队列

为了简单起见,我只是包含了队列的示例)

c++ multithreading atomic deadlock
1个回答
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(); }

© www.soinside.com 2019 - 2024. All rights reserved.