信号量完全适用于生产者-消费者模型,尽管它还有其他用途。您的程序逻辑负责确保根据等待次数发布正确数量的帖子。如果您发布信号量并且没有人在等待它,那么当他们等待时,他们会立即继续。如果您的问题可以用信号量的计数值来解释,那么使用信号量应该很容易解决。
条件变量在某些方面更加宽容。例如,您可以使用 cond_broadcast 唤醒所有服务员,而生产者不知道有多少服务员。如果你 cond_signal 一个没有人在等待它的 condvar,那么什么也不会发生。如果您不知道是否会有听众感兴趣,这很好。这也是为什么侦听器应始终在等待之前检查持有的互斥锁的状态 - 如果他们不这样做,那么他们可能会错过一个信号并且直到下一个信号才会醒来(可能永远不会)。
因此,条件变量适用于通知相关方状态已更改:您获取互斥锁、更改状态、发送信号(或广播)condvar 并释放互斥锁。如果这描述了您的问题,那么您就处于 condvar 领域。如果不同的听众对不同的状态感兴趣,你可以广播,他们会依次醒来,确定他们是否找到了他们想要的状态,如果没有,就再等。
用互斥锁和信号量尝试这种事情确实非常棘手。当您想要获取互斥体,检查某些状态,然后等待信号量进行更改时,问题就来了。除非您可以原子地释放互斥体并在信号量上等待(在 pthread 中您不能这样做),否则您最终会在持有互斥体的同时等待信号量。这会阻止互斥体,这意味着其他人无法接受它来进行您关心的更改。因此,您会很想以一种取决于您的特定要求的方式添加另一个互斥锁。也许另一个信号量。结果通常是带有有害竞争条件的错误代码。
条件变量避免了这个问题,因为调用 cond_wait 会自动释放互斥体,释放它以供其他人使用。在 cond_wait 返回之前重新获得互斥锁。
IIRC 可以仅使用信号量来实现一种 condvar,但是如果您要与 condvar 一起实现的互斥锁需要具有 trylock,那么这是一个严重的问题,并且定时等待已经结束。不建议。所以不要假设你可以用 condvar 做的任何事情都可以用信号量来完成。当然,互斥体可以具有信号量所缺乏的良好行为,主要是避免优先级反转。