У меня возникла тупиковая ситуация, которую я не могу объяснить с помощью приведенного ниже кода. Я ожидал, что код должен работать из-за ложного пробуждения, но думаю, что что-то упускаю. Я проверил это Взаимная блокировка переменной условия, но безуспешно.
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++ активно развивается, и новые стандарты регулярно добавляют новые возможности.
Ваш 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();
}