gpt4 book ai didi

c++ - 一般来说,处理虚假唤醒的正确方法是什么?

转载 作者:搜寻专家 更新时间:2023-10-31 00:52:19 27 4
gpt4 key购买 nike

在下面的选项中,有没有正确的方法来处理使用条件变量时的虚假唤醒?

1) 使用 bool 值将 wait(unique_lock_ul) 放入无限的 while 循环中

unique_lock<mutex> ul(m); 
while(!full)
cv.wait(ul);

2) 与 if 相同

unique_lock<mutex> ul(m); 
if(!full)
cv.wait(ul);

3) 在 wait() 中放置一个条件,例如使用 lambda 函数

unique_lock<mutex> ul(m); 
cv.wait(ul, [&](){return !full;});

如果这些都不正确,如何轻松应对虚假唤醒?

我对 C++ 中的条件变量相当陌生,我不确定我阅读的某些代码是否处理虚假唤醒的情况。

最佳答案

简短的回答是,您的代码可能正确也可能错误;您没有确切说明 full 是如何被操纵的。

C++ 代码的个别位永远不是线程安全的。线程安全是代码的关系属性;如果两位代码永远不会导致竞争条件,那么它们就可以是线程安全的。

但是一点代码永远都不是线程安全的;说某物是线程安全的就像说某物是“相同的高度”。


“monkey see monkey do”条件变量模式是这样的:

template<class T>
class cv_bundle {
std::mutex m;
T payload;
std::condition_variable cv;
public:
explicit cv_bundle( T in ):payload(std::move(in)) {}

template<class Test, class Extract>
auto wait( Test&& test, Extract&& extract ) {
std::unique_lock<std::mutex> l(m);
cv.wait( l, [&]{ return test(payload); } );
return extract(payload);
}
template<class Setter>
void load( Setter&& setter, bool only_one = true ) {
std::unique_lock<std::mutex> l(m);
bool is_set = setter( payload );

if (!is_set) return; // nothing to notify
if (only_one)
cv.notify_one();
else
cv.notify_all();
}
};

test 接受一个 T& payload 并在有东西要消耗时返回 true(即,唤醒不是虚假的)。

extract 获取一个 T& payload 并返回您想要从中获取的任何信息。它通常应该重置有效负载。

settertest 将返回 true 的方式修改 T& payload。如果这样做,它会返回 true。如果选择不这样做,则返回 false

所有 3 个都在锁定访问 T payload 的互斥锁中被调用。

现在,您可以生成变体,但很难做到正确。例如,不要假设原子负载意味着您​​不必锁定互斥量。

虽然我将这 3 个东西捆绑在一起,但您可以对一堆条件变量使用单个互斥锁,或者将互斥锁用于条件变量之外的其他对象。有效载荷可以是一个 bool 值、一个计数器、一个数据 vector ,或者更奇怪的东西;通常,它必须始终受到互斥锁的保护。如果它是原子的,则在被修改的值和通知之间的开放时间间隔内的某个时间点,必须锁定互斥体,否则您可能会丢失通知。

手动循环控制而不是传入lambda是一种修改,但是描述什么样的手动循环是合法的,哪些是竞争条件是一个复杂的问题。

实际上,除非我有非常充分的理由,否则我避免离开这种猴子看猴子做的“ cargo 崇拜”风格的条件变量使用。然后我被迫阅读 C++ 内存和线程模型,这让我很不高兴,这意味着我的代码很可能不正确。

请注意,如果传入的任何 lambda 表达式返回并回调到 cv_bundle,我显示的代码将不再有效。

关于c++ - 一般来说,处理虚假唤醒的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52192203/

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