[英]Deadlock when using condition.wait()
Code found here: http://coliru.stacked-crooked.com/a/7942a18fe11ea544 在此处找到代码: http : //coliru.stacked-crooked.com/a/7942a18fe11ea544
I'm experimenting with the condition.wait without a timeout and am finding myself in a deadlock. 我正在尝试condition.wait而没有超时,却发现自己陷入了僵局。 The gist of what i'm trying to do is sit in a lock until i've determined that i've created a new file.
我要执行的操作的要旨是坐在一个锁中,直到我确定已创建一个新文件为止。 I'd set a flag and notify the thread, which will then (in my real program) trigger a callback function.
我将设置一个标志并通知线程,然后该线程将(在我的真实程序中)触发一个回调函数。 at the end of the running, i want to shut down all my threads.
在运行结束时,我想关闭所有线程。 I set my loop variable to false, then notify one, which i assumed would unblock the thread.
我将循环变量设置为false,然后通知一个,我认为这将取消阻塞线程。 Am i mistaken that this would ignore what the predicate evaluated?
我是否误认为这会忽略谓词评估的内容?
Could someone suggest a better thread layout that would correct the deadlock? 有人可以建议一个更好的线程布局来纠正死锁吗? Thanks.
谢谢。
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>
#include <condition_variable>
using namespace std::chrono_literals;
std::atomic_bool new_file_created_{false};
std::atomic_bool run_data_logger_{false};
std::condition_variable file_monitor_condition_;
std::mutex file_monitor_mutex_;
std::thread test_thread_;
void file_monitor_thread_func()
{
using namespace std::chrono_literals;
while (run_data_logger_)
{
std::unique_lock<std::mutex> lock(file_monitor_mutex_);
file_monitor_condition_.wait(lock, [] { return new_file_created_.load(); });
if (new_file_created_)
{
std::cout<< "New File Created" << std::endl;
new_file_created_ = false;
//do some stuff
}
else
{}
}
}
void end_the_thread()
{
std::cout << "Ending the Thread" << std::endl;
run_data_logger_ = false;
file_monitor_condition_.notify_one();
if (test_thread_.joinable())
test_thread_.join();
std::cout << "Thread Ended" << std::endl;
}
void trigger_new_file()
{
new_file_created_ = true;
file_monitor_condition_.notify_one();
}
void start_the_thread()
{
run_data_logger_ = true;
test_thread_ = std::thread(file_monitor_thread_func);
trigger_new_file();
}
int main()
{
for (int j = 0; j<10; j++)
{
start_the_thread();
std::this_thread::sleep_for(500ms);
end_the_thread();
}
}
After new_file_created_
becomes true
for the first time, file_monitor_thread_func
resets it to false
then loops around and waits for it to become true
again. 在
new_file_created_
首次变为true
之后, file_monitor_thread_func
重置为false
然后循环并等待它再次变为true
。 But no one ever sets it to true
again. 但是没有人再次将其设置为
true
。
A condition_variable
is used together with a mutex
, which is not a cosmetic feature. condition_variable
与mutex
一起使用, mutex
不是外观特征。 You seem to be under the impression that 您似乎给人的印象是
std::unique_lock<std::mutex> lock(file_monitor_mutex_);
is enough to satisfy the precondition of the wait
method; 足以满足
wait
方法的先决条件; but a mutex conceptually only makes sense if it's used for mutual exclusion . 但是互斥锁从概念上讲只有在用于互斥时才有意义 。 You aren't using it as such, the mutex is only ever locked inside
file_monitor_thread_func
, so mutual exclusion on state changing operations is not guaranteed. 您并没有像这样使用它,互斥锁仅被锁定在
file_monitor_thread_func
,因此不能保证状态更改操作互斥。
A telltale sign that you are using the monitor incorrectly is that you felt the need to use atomic objects, as the mutual exclusion (that is a prerequisite) guarantees that normal objects can be used. 一个不正确使用监视器的迹象表明,您觉得需要使用原子对象,因为互斥(这是前提)保证可以使用普通对象。
There is simply no way to combine a condition and atomic objects . 根本没有办法将条件和原子对象结合起来 。 They belong in different designs.
它们属于不同的设计。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.