C++:如何在 UI 线程和 worker std::thread 之间使用 std::condition_variable

标签 c++ multithreading c++11 mutex condition-variable

我正在尝试使用 std::condition_variable来自 C++11,用于 UI 线程和工作线程之间的数据事务。

情况:
m_calculated_value 是经过复杂逻辑计算得到的值。这是从 UI 线程触发事件所必需的。 UI 线程调用MyClass::GetCalculatedValue 获取m_calculated_value 的值,该值需要由工作线程函数MyClass::ThreadFunctionToCalculateValue 计算.

代码:

std::mutex              m_mutex;
std::condition_variable m_my_condition_variable;
bool                    m_value_ready;
unsigned int            m_calculated_value;


// Gets called from UI thread
unsigned int MyClass::GetCalculatedValue() {

    std::unique_lock<std::mutex> lock(m_mutex);
    m_value_ready = false;

    m_my_condition_variable.wait(lock, std::bind(&MyClass::IsValueReady, this));

    return m_calculated_value;
}


bool MyClass::IsValueReady() {

    return m_value_ready;
}

// Gets called from an std::thread or worker thread
void MyClass::ThreadFunctionToCalculateValue() {

    std::unique_lock<std::mutex> lock(m_mutex);

    m_calculated_value = ComplexLogicToCalculateValue();
    m_value_ready = true;

    m_my_condition_variable.notify_one();
}

问题:
但问题是 m_my_condition_variable.wait 永远不会返回。

问题:
我在这里做错了什么?

让 UI 线程等待来自工作线程的条件变量信号是否正确?我如何摆脱 condition_variable 由于工作线程函数中的错误而永远不会触发的情况?有什么办法可以在这里使用超时吗?

尝试了解它的工作原理:
我在许多示例中看​​到,他们在 condition_var.wait 周围使用 while 循环检查 bool 变量的状态。在变量上循环有什么意义? 我不能期望 m_my_condition_variable 在从其他线程调用 notify_one 时从 wait 返回吗?

最佳答案

最有可能发生的事情: 您的工作线程拥有并持有互斥锁,直到计算完成。主线程必须等到它可以获取锁。 worker before 释放锁(在析构函数中)时将向 CV 发出信号,到那时,没有其他想要等待条件变量的线程可以获得它仍然占用的锁通知线程。因此,另一个线程在收到通知时永远没有机会等待条件变量,因为它只是在通知事件发生后设法获取锁,导致它无限等待。

解决方案是删除 MyClass::ThreadFunctionToCalculateValue() 中的锁获取,那里根本不需要,或者至少不应该。

但无论如何,你为什么要重新发明轮子?对于此类问题,std::future已创建:

auto future = std::async(std::launch::async, ComplexLogicToCalculateValue);
bool is_ready = future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
auto result = future.get();

在这里,您可以轻松定义超时,您不必担心 condition_variables 等。

Cant I expect m_my_condition_variable to return out of wait when notify_one is called from other thread ?

No ,不完全是。虚假唤醒仍然可能发生。

关于C++:如何在 UI 线程和 worker std::thread 之间使用 std::condition_variable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46620817/

相关文章:

C++ valarray/模板类不工作

c++ - 我什么时候应该使用 std::any

c++ - 自定义支持 __attribute__((format))

c++ - Visual Studio C++ 应用程序无法在 32 位计算机上运行

Java多线程,主线程为什么停止了?

multithreading - 使用并行排序和多个字段对列表进行排序

java - 如何使方法线程安全,即使我忘记在不更改文件的情况下在方法或 block 级别添加同步?

c++ - 在 C++11 中使用 SFINAE 在具有相同签名的两个函数之间进行选择

c++ - 为什么我必须调用 operator<< 作为 SFINAE 使用 void_t 的方法?

c++ - 在 g++ 4.8.1 编译器中测试 atomic_int