C++ 条件变量:等待并通知健壮性

C++ 条件变量:等待并通知健壮性,c++,multithreading,condition-variable,C++,Multithreading,Condition Variable,这是在大多数示例中使用条件变量的方式: std::mutex mutex_; //declared somehere 线程1: if (!pred) { std::unique_lock<std::mutex> lock(mutex_); cv_.wait(lock, [this](){return pred}); } 似乎有一个窗口,线程1检查pred,发现它为false,并继续获取锁。然而,在它可以之前,线程2使pred为true,并通知条件变量并继续。线程1现在

这是在大多数示例中使用条件变量的方式:

std::mutex mutex_; //declared somehere
线程1:

if (!pred) {
   std::unique_lock<std::mutex> lock(mutex_);
   cv_.wait(lock, [this](){return pred});
}
似乎有一个窗口,线程1检查pred,发现它为false,并继续获取锁。然而,在它可以之前,线程2使pred为true,并通知条件变量并继续。线程1现在获得锁,并卡在此条件变量上

这个案件通常如何处理?因为有人提到,在通知之前锁定是一种悲观,因此不应该这样做

我知道我可以使用超时,但这仍然不能解决这个问题。这是否意味着,如果不存在竞争条件,等待/通知条件变量时,总是需要锁定

编辑

有一条评论提到,在thread2中,我们应该在使谓词为“true”之前获得相同的锁。但是,考虑下面的场景:

存在一个有界队列,其中有一个生产者(thread1)和一个消费者(thread2)。假设队列的大小为1000。我们将当前队列大小的计数保持为原子int,以便生产者和消费者可以在不使用锁的情况下同时修改它。 在上述情况下,谓词为:is size of queue<1000


现在,如果在thread2中,我在修改这个谓词之前先锁定了它,也就是说,递减count,它不是破坏了count作为原子的全部目的吗?另外,我希望它是原子的,因为通常的操作(即当队列大小<1000时)会很快。

没有竞争。
if
只是一个额外的优化,您可以使用
if(true)
,它仍然可以工作。为什么没有竞争?在获取锁之前,如果线程2执行通知并继续,那么线程1将被卡在等待中,也将被卡在标准中。同样,thread1在等待之前不必che(ck)任何内容。检查不会更改任何内容,除非在某些情况下线程根本不会进入等待状态。这不是“大多数示例”中使用条件变量的方式。大多数示例从不访问(不只是更改)除非mtx被锁定,否则将使用谓词。这就是mtx的要点:完全保护谓词。cvar本身只是一个通知机制。如果您想对谓词使用原子,可以,但不保存任何内容。cvar+mtx对的目的是能够开始等待cvar通知并释放对mtx的访问权限原子(据你所知)为了让其他人能够锁定mtx,请更改谓词状态并调用cvar notify。@user1715122听起来您似乎明白这一点。也许可以为无锁插入定制代码,但在您自杀之前,花点时间看看传统模型是否足够。很可能,这取决于你能以多快的速度从队列中获取数据,从而最大限度地减少锁定时间。我认为至少值得一到两次测试。
//makes pred true
   cv_.notify_one();