有人可以举一个 C++ 条件变量的例子,其中通知线程 B 的线程 A 必须在通知线程 B 后响应?

Posted

技术标签:

【中文标题】有人可以举一个 C++ 条件变量的例子,其中通知线程 B 的线程 A 必须在通知线程 B 后响应?【英文标题】:can someone give an example of C++ condition_varible where the thread A that notifies thread B has to respond after thread B is notified? 【发布时间】:2020-11-27 17:09:42 【问题描述】:

例如,假设线程 B 正在等待一个条件变量,线程 A 通知线程 B。唤醒后,线程 B 做某事,然后通知 A,以便 A 做某事。我需要这个,因为如果线程 B 执行某些操作,我需要更新线程 A 中的 GUI。下面的代码是我脑海中的骨架。但是,我担心线程 B 可能会在线程 A 进入等待阶段之前通知 A。这是一个合理的担忧吗?在这种情况下,人们通常会怎么做?我在网上找到的所有condition_variable的例子都没有通知线程必须做依赖于通知线程的事情的情况。

std::mutex mtx;
std::condition_variable cond;

void threadA()
    std::unique_lock<std::mutex> guard(mtx);
    cond.notify_one();
    cond.wait(guard, [&]()return some bool expression;)
    // do something//


void threadB()
    std::unique_lock<std::mutex> guard(mtx);
    cond.wait(guard, [&]()return some bool expression;)
    // do something//
    cond.notify_one();


【问题讨论】:

您能具体说明some bool expression 的真正含义吗?而且,这个条件是如何在通知线程中设置的?这对于回答您的问题可能非常重要。 【参考方案1】:

类似的东西你可以试试。

   std::mutex mtx;
    std::condition_variable cond;
    bool flag1 = false;
    bool flag2 = false;
    
    void threadA()
        
        std::unique_lock<std::mutex> guard(mtx);
        flag1 = true;
        cond.notify_one();
        
    
        
        std::unique_lock<std::mutex> guard(mtx);
        while(!flag2)
            cond.wait(guard, [&]()return some bool expression;)
        // do something//
        
    
    
    void threadB()
        
        std::unique_lock<std::mutex> guard(mtx);
        while(!flag1)
            cond.wait(guard, [&]()return some bool expression;)
        // do something//
        
    
        
        std::unique_lock<std::mutex> guard(mtx);
        flag2 = true;
        cond.notify_one();
        
    

【讨论】:

【参考方案2】:

使用std::atomic_flag 了解A 何时进入等待阶段。不要使用普通标志来避免数据争用。

#include <condition_variable>
#include <atomic>

std::mutex mtx;
std::condition_variable cond;
std::atomic_bool a_has_entered = false;

void threadA()
    std::unique_lock<std::mutex> guard(mtx);
    cond.wait(guard, [&]()a_has_entered = true;return some_bool_expression;);
    // do something//


void threadB()
    std::unique_lock<std::mutex> guard(mtx);
    // do something//
    while(!a_has_enterd);
    cond.notify_one();

或者使用另一个conditon_variable避免资源泄露,如下

std::mutex mtx, a_has_entered_guard_mtx;
std::condition_variable cond;
std::condition_variable cond_a_has_entered;
bool a_has_entered = false;

void threadA()
    std::unique_lock<std::mutex> guard(mtx);
    cond.wait(guard, [&]()std::lock_guard guard a_has_entered_guard_mtx;
                a_has_entered = true;
                cond_a_has_entered.notify_all();
                return some_bool_expression;);
    // do something//


void threadB()
    std::unique_lock<std::mutex> guard(mtx);
    // do something//
    std::unique_lock a_has_entered_guard a_has_entered_guard_mtx;
    cond_a_has_entered.wait(a_has_entered_guard, [&]()return a_has_entered;);
    cond.notify_all();

【讨论】:

以上是关于有人可以举一个 C++ 条件变量的例子,其中通知线程 B 的线程 A 必须在通知线程 B 后响应?的主要内容,如果未能解决你的问题,请参考以下文章

C++中Find函数如何使用?请举例子,我是菜鸟,不要说得太复杂

等待条件的线程的有序通知(C++,boost)

使用 inotify 通知新文件

C++笔记--条件变量

C++笔记--条件变量

JAVA枚举可以用来做啥?举一个简单的例子(用枚举、不用)