c++ - std::condition_variable::wait() 如何评估给定的谓词?

标签 c++ predicate condition-variable

上下文:

在每个示例中,我都可以看到关于 std::condition_variable::wait() 的使用,包括那些来自 cppreference.com 的示例,从来没有任何同步机制用于保护谓词评估免受数据竞争。

例如:

std::mutex m;
std::condition_variable cv;
int i = 0;

void waiting_func()
{
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, [](){return i > 0;}); // No lock/unlock around the access of the global and shared variable i.
    // ...
}

问题:

如果没有这样的同步,即使来自信誉良好的来源示例,我猜那是因为没有必要。
但我想知道为什么? std::condition_variable::wait() 如何评估谓词以确保它是线程安全的?

我的想法:

我想到了两种可能性:

  1. ) 或者,谓词保证被原子评估(我从来没有读过这样的东西,因此我的问题)
  2. ) 或者,当发送notify 信号时,std::condition_variable::wait() 函数在 求值之前重新获取互斥量谓词。

在点 2.) 的情况下,如果修改 i 的线程(并调用 std::condition_variable::notify_one ()) 在执行此操作之前锁定互斥体 m

例如:

void modify_func()
{
    {
        std::scoped_lock<std::mutex> lk(m); // Acquire the mutex
        i += 1;                             // Modify i
    }                                       // Release the mutex
    cv.notify_one();
}

当然,还有一种可能是我的理解完全错误,然后我就错过了重点。

无论如何,我真的很惊讶我在文档中找不到任何关于它的细节。

最佳答案

您的第二个选择是正确的。如 cppreference 所述,谓词重载表现为

while (!pred()) {
    wait(lock);
}

wait(lock) 总是在返回前重新锁定。请参阅 [thred.condition.condvar]/12 中的 wait 后置条件和谓词重载行为 [thread.condition.condvar]/15 C++17 标准(草案 N4659)。

是的,在修改 i 时必须锁定互斥体,即使它是原子的。参见例如this question .

关于c++ - std::condition_variable::wait() 如何评估给定的谓词?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60391446/

相关文章:

c++ - 通过它自己的条件变量c++控制每个线程

c++ - 模板定义如何与模板声明匹配?

c++ - 在特定情况下不发送 UDP 广播

C++ 运算符优先级示例

c++ - <functional>中有功能组合的东西吗?

c - 如何使用条件变量

c++ - 在构造函数中使用 shared_from_this()

c++ - 包装谓词仿函数

vector - 有没有办法根据谓词排出向量的一部分?

multithreading - pthread_cond_timedwait 超时后线程是否拥有互斥锁?