一个条件变量是否可能“错过”通知调用?

3
我想知道条件变量是否可能“错过”通知调用。我的情况如下。
给定一个互斥锁mu和一个谓词P(!queue.empty())...
线程A:在程序的整个生命周期内持续存在。等待于mu和P上的条件变量。在获取mu并验证队列不为空后,它将从队列中弹出一个项目。
线程B:一个函数,将获取mu,将其推入队列。
线程C:与B相同。
线程B和C同时产生。
在这种情况下,B首先获取mu,将其推入队列,放弃mu并调用notify。在B调用notify并放弃mu之间,C获取mu,将其推入队列并调用notify。最后,A获取mu,继续从队列中弹出一个项目并处理它。但是A只对其中一个notify调用起作用。
如果您想逐个处理队列中的项目,则似乎会创建堆积。
这是可能发生的情况吗?我们需要意识到这一点吗?例如,在A中,弹出直到队列为空?还是语言处理了这个问题?

1
就像你说的那样,一直弹出直到队列为空。条件变量不会跟踪有多少个通知调用正在等待。 - undefined
A只对其中一个notify调用起作用有什么问题?你认为A接下来会做什么? - undefined
问题是如果A不在两个通知调用上都采取行动,那么我就有一些在队列中但没有被处理的项目。 - undefined
1个回答

2
如果你想一个一个地处理队列中的项目,这似乎会导致积压。这是可能发生的情况吗?我们需要注意吗?例如,在A中,弹出直到队列为空?或者这由语言处理?
是的,这是可能发生的情况,你应该意识到它。在你描述的情况下,等待可能会一次唤醒一次(队列中有两个项目),两次唤醒(每个项目一次)甚至N次唤醒(没有项目的虚假唤醒)。这就是为什么在唤醒后始终检查谓词,并确保在重新等待条件之前谓词为false。弹出直到队列为空是一个合理的解决方案。

1
cv.wait()在谓词为真时(即不阻塞)会立即返回,而不管是否有通知。因此,如果谓词是(!queue.empty())或类似的条件,并且队列中有两个项目,它将一直立即返回,直到队列为空(并不一定是接收到的通知数量!)并循环两次。所以当wait()返回时,你可能不需要做任何其他操作,只需弹出队列一次,因为wait()将继续立即返回,直到队列为空。你的谓词具体是什么? - undefined
抱歉之前没有详细说明 - 我以为你在使用pthread。Boost或C++线程会稍微改变一些情况。 - undefined
C++ 线程,这就是我困惑的地方。我的谓词是 {return !queue.empty()}。我的理解是,即使谓词满足条件,它也会在等待期间阻塞直到获取锁定,或者我理解错了吗?如果是这样的话,那也不是我想要的。 - undefined
1
好的,在调用wait之前,你应该先获取锁,这是使用wait的前提条件。wait会在检查谓词之后解锁互斥量并等待。如果谓词为假,则返回时仍然保持锁定状态。是的,一旦解锁,它将等待信号(或者被虚假唤醒),然后重新获取锁再返回。 - undefined
1
@nromer 不管在释放锁之前是否检查队列是否为空都无关紧要。无论哪个消费者线程获得锁,都应该发现队列非空,并且不需要等待任何东西。只是不要等待已经发生的事情。 - undefined
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接