std::condition_variable::wait()如何评估给定的谓词
How does std::condition_variable::wait() evaluate the given predicate?
上下文:
在我看到的关于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()
如何评估谓词以使其线程安全?
我的想法:
我提出了两种可能性:
- (或者,谓词保证是原子求值的(我从来没有读过这样的东西,因此我提出了问题(
- )或者,当发送通知信号时,
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)
总是在返回之前重新定位。参见C++17标准(草案N4659(的[thred.condition.convar]/12中的wait
后条件和[thread.convation.convar]/15中的谓词重载行为。
是的,在修改i
时,互斥体必须被锁定,即使它是原子的。例如,请参见此问题。
相关文章:
- std::condition_variable::wait()如何评估给定的谓词
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- c++11评估顺序(未定义的行为)
- 如何使用"equal to"以外的评估编写开关语句
- 嵌套 if 中没有返回评估
- 懒惰的参数评估try_emplace?
- 如何在 STL 函数中找到传递给谓词的元素的索引?
- 在实践中,在运行时为零的乘法中是否有任何"lazy"评估
- 为 C++11 算法组合多个谓词
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- C++17:使用 std::optional 来评估枚举是否包含值
- CNTK:->转发或 ->评估某些电脑上的崩溃,而不是其他电脑上的崩溃
- ConstexPR :GCC比Clang更努力地评估ConstexPR
- C++:Constexpr斐波那契数列评估
- C++能保证论点评估的原子性吗?
- 在编译时评估函数开销的通用方法
- 处理 std::enable_if<...中谓词的逻辑"OR">
- std::map与谓词与初始化列表
- 尝试使用谓词函数会导致错误:"std::sort"未找到匹配的重载函数
- 评估C 中的二元谓词