此代码简化了实际项目代码。主线程创建工作线程并等待std :: condition_variable工作线程真正启动。在下面的代码中,std :: condition_variable在current_thread_state变为" ThreadState :: Stopping"之后醒来。 - 这是来自工作线程的第二个通知,即当第一个通知后,当current_thread_state变为" ThreadState :: Starting"时,主线程没有被唤醒。结果是僵局。为什么会这样?为什么std :: condition_variable在第一次thread_event.notify_all()之后没有被唤醒?
int main()
{
std::thread thread_var;
struct ThreadState {
enum Type { Stopped, Started, Stopping };
};
ThreadState::Type current_thread_state = ThreadState::Stopped;
std::mutex thread_mutex;
std::condition_variable thread_event;
while (true) {
{
std::unique_lock<std::mutex> lck(thread_mutex);
thread_var = std::move(std::thread([&]() {
{
std::unique_lock<std::mutex> lck(thread_mutex);
cout << "ThreadFunction() - step 1\n";
current_thread_state = ThreadState::Started;
}
thread_event.notify_all();
// This code need to disable output to console (simulate some work).
cout.setstate(std::ios::failbit);
cout << "ThreadFunction() - step 1 -> step 2\n";
cout.clear();
{
std::unique_lock<std::mutex> lck(thread_mutex);
cout << "ThreadFunction() - step 2\n";
current_thread_state = ThreadState::Stopping;
}
thread_event.notify_all();
}));
while (current_thread_state != ThreadState::Started) {
thread_event.wait(lck);
}
}
if (thread_var.joinable()) {
thread_var.join();
current_thread_state = ThreadState::Stopped;
}
}
return 0;
}
答案 0 :(得分:2)
一旦调用notify_all
方法,主线程和工作线程(完成工作后)都试图锁定thread_mutex
互斥锁。如果您的工作负载无关紧要,例如在您的示例中,工作线程可能会在主线程之前获取锁定,并在主线程读取之前将状态设置回ThreadState::Stopped
。这导致死锁。
尝试添加重要的工作量,例如
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
到工作线程。死锁现在不太可能。当然,这不是解决您的问题的方法。这只是为了说明问题。
答案 1 :(得分:0)
你有两个线程竞争:一个写入current_thread_state
两次的值,另一个读取current_thread_state
的值一次。
事件序列是否是您所期望的写 - 读 - 读或写 - 读 - 写是不确定的,两者都是您的应用程序的有效执行。