gpt4 book ai didi

c++ - 不持有锁的条件变量信号

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:07:32 26 4
gpt4 key购买 nike

所以我刚刚发现,如果您没有持有 c++11 中的锁,则向条件变量发出信号是合法的。这似乎为某些令人讨厌的竞争条件打开了大门:

std::mutex m_mutex;
std::condition_variable m_cv;

T1:
std::unique_lock<std::mutex> lock(m_mutex);
m_cv.wait(lock, []{ return !is_empty(); });

T2:
generate_data();
m_cv.notify();

是否保证 T1 永远不会在我们首先检查 is_empty()(它返回 true)然后被 T2 抢占的情况下结束,T2 创建一些数据并向条件变量发出信号,然后我们才能真正等待它?

如果这保证有效(我猜是这样,否则它看起来像是一个故意糟糕的 API 设计),这实际上是如何为 linux 和 stdlibc++ 实现的?看来我们需要另一把锁来避免这种情况。

最佳答案

std::condition_variable::wait 中检查谓词和等待不是原子执行的(解锁锁和 sleep 原子执行的)。如果另一个线程有可能在该线程持有互斥量时更改谓词的值,则通知有可能在谓词检查和进入休眠之间发生,并有效地丢失。

在您的示例中,如果 T2 中的 generate_data() 可以更改 is_empty() 的结果而无需保留 m_mutex,有可能在 T1 检查 is_empty() 和休眠 m_cv 之间发生通知。在谓词更改和通知之间的任何时间持有互斥锁足以保证谓词检查和另一个线程中的 wait 调用的原子性。这可能看起来像:

{
std::lock_guard<std::mutex> lk(m_mutex);
generate_data();
}
m_cv.notify();

甚至

generate_data();
std::lock_guard<std::mutex>(m_mutex); // Lock the mutex and drop it immediately
m_cv.notify();

关于c++ - 不持有锁的条件变量信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21439359/

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