尽管信号量还有其他用途,但它适用于生产者 - 消费者模型。您的程序逻辑负责确保为等待次数提供适当的帖子数量。如果你发布一个信号而没有人等待,那么当他们等待时,他们立即继续。如果您的问题可以用信号量的计数值来解释,那么使用信号量应该很容易解决。
条件变量在某些方面有点宽容。例如,您可以使用cond_broadcast唤醒所有服务员,而制片人不知道有多少人。如果你没有人在等待它,cond_signal condvar然后没有反应。如果你不知道是否有兴趣的听众,这很好。这也是为什么聆听者应该总是在等待之前检查互斥状态 - 如果他们不这样,他们就会错过一个信号,直到下一个(可能永远不会)醒来。
所以一个条件变量适用于通知感兴趣的各方状态已经改变:你获得互斥量,改变状态,信号(或广播)condvar并释放互斥量。如果这描述你的问题,你在condvar领土。如果不同的听众对不同的状态感兴趣,你可以直接播放,然后每个人都会醒来,找出他们是否已经找到了他们想要的状态,如果不再等待。
用互斥量和信号量来尝试这种事情确实非常困难。问题出现在你想要获取互斥锁时,检查一些状态,然后等待信号量发生变化。除非你可以自动释放互斥量并等待信号量(在pthread中你不能),否则最终等待信号量同时持有互斥量。这会阻止互斥体,这意味着其他人无法将其用于执行您关心的更改。所以你会被诱惑添加另一个互斥体,这取决于你的具体要求。也许是另一个信号量。结果通常是不正确的代码,有害的竞态条件。
条件变量可以避免这个问题,因为调用cond_wait会自动释放互斥锁,释放它以供其他人使用。在cond_wait返回之前,互斥体会重新获得。
IIRC有可能仅使用信号量来实现一种condvar,但是如果您要实现与condvar一起使用的互斥锁需要使用trylock,那么它是一个严重的头部划伤,并且定时等待。不建议。所以不要认为你可以用condvar做什么都可以用信号量来完成。此外,当然互斥体可以有很好的信号量缺乏行为,主要是避免优先级倒置。
我刚刚意识到“正确初始化旗语”是不明确的。信号量是否设置为1或0?我会说它应该被设置为0.然后,信号量是否保护凸轮 - >状态? – Blaisorblade 2014-06-01 22:45:33
在其他答案中提到的第二个片段中,当互斥体未被释放时,您的线程将被阻塞。所以你的`sem_wait`方法永远不会返回,因为没有其他线程可以获得互斥体并调用`sem_signal`。但是,如果我在`sem_wait`之前释放互斥并在等待之后再次请求它,我不会发生什么。我知道这些步骤不是原子的,那么会发生什么? – sevenkplus 2016-10-03 15:31:54