gpt4 book ai didi

c++ - std::condition_variable 在来自其他线程的 std::condition_variable::notify_all() 之后未正确唤醒

转载 作者:行者123 更新时间:2023-11-28 02:22:46 26 4
gpt4 key购买 nike

此代码是实际项目代码的简化。主线程创建工作线程并使用 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;
}

最佳答案

一旦您调用了notify_all 方法,您的主线程和您的工作线程(在完成其工作之后)都会尝试锁定thread_mutex 互斥量。如果您的工作负载很小,就像在您的示例中一样,工作线程可能会在主线程之前获得锁定,并在主线程读取它之前将状态设置回 ThreadState::Stopped 。这会导致死锁。

尝试增加大量的工作量,例如

std::this_thread::sleep_for( std::chrono::seconds( 1 ) );

到工作线程。现在死锁的可能性要小得多。当然,这不能解决您的问题。这只是为了说明问题。

关于c++ - std::condition_variable 在来自其他线程的 std::condition_variable::notify_all() 之后未正确唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31789457/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com