|
|
1
61
信号量非常适合生产者-消费者模型,尽管它还有其他用途。你的程序逻辑负责确保为等待的次数发布正确数量的帖子。如果你发布了一个信号量,但还没有人在等待,那么当他们等待时,他们会立即继续。如果你的问题可以用信号量的计数值来解释,那么用信号量应该很容易解决。 条件变量在某些方面更宽容一些。例如,您可以使用cond_broadcast唤醒所有服务员,而制作人不知道有多少服务员。如果你在没有人等待的情况下发出condvar信号,那么什么都不会发生。如果你不知道是否会有听众感兴趣,这很好。这也是为什么监听器在等待之前应该始终检查互斥体的状态——如果他们没有检查,那么他们可能会错过一个信号,直到下一个信号才醒来(这可能永远不会)。 因此,条件变量适合通知相关方状态已更改:您获取互斥体,更改状态,用信号(或广播)发送condvar并释放互斥体。如果这描述了你的问题,那么你就在condvar领域。如果不同的听众对不同的州感兴趣,你可以直接广播,他们会依次醒来,弄清楚他们是否找到了他们想要的州,如果没有,再等一次。 用互斥体和信号量尝试这种事情确实非常困难。当你想获取互斥体,检查一些状态,然后等待信号量的变化时,问题就来了。除非你能原子性地释放互斥体并等待信号量(在pthreads中你不能),否则你最终会在持有互斥体的同时等待信号量。这会阻止互斥体,这意味着其他人无法利用它来做出你关心的更改。因此,您可能会倾向于根据您的特定要求添加另一个互斥体。也许还有另一个信号。结果通常是错误的代码和有害的种族条件。 条件变量避免了这个问题,因为调用cond_wait会自动释放互斥体,将其释放给其他人使用。在cond_wait返回之前,互斥体被恢复。 IIRC可以仅使用信号量来实现一种condvar,但如果你要实现的与condvar一起使用的互斥体需要具有trylock,那么这是一个严重的问题,并且超时等待已经结束。不推荐。因此,不要想当然地认为你可以用condvar做的任何事情都可以用信号量来完成。当然,互斥体可以具有信号量所缺乏的良好行为,主要是避免优先级反转。 |
|
2
19
条件允许你做一些信号量不会做的事情。
例如,假设您有一些需要互斥体的代码,称为
条件变量还允许您让
所有
线程等待条件变量通过
当然,有时你不需要条件变量,所以根据你的要求,其中一个可能更好。 |
|
|
3
5
第二段很生动,不要这样做。
其他答案对相对优点进行了很好的讨论;我只是补充一下
除此之外,我只是更习惯于为此设置条件变量,因为它们是你在Java中使用的,即使它们可以帮助你在检查共享标志时避免竞争。 事实上,在第二段代码中,您没有任何锁来保护cam的读取->状态,因此它是通过数据竞争访问的。在这个特定的例子中,大多数平台都会让你逃脱惩罚,但根据POSIX和下一个C/C++标准的内存模型,这具有未定义的语义。 事实上,如果另一个线程分配了一个新的凸轮结构并覆盖了凸轮,那么真正的竞争条件是可能的;等待线程可能会看到“cam”指针的更新,而看不到cam的初始化->状态。事实上,在这种情况下和一般情况下,第二个片段是在自找麻烦。 |
|
|
4
0
在第二个代码片段中,您多次获得锁,但从未释放它。 一般来说,你放弃的状态可以完全由信号量表示,然后你就可以使用它。锁结构的大小较小,检查/设置/释放所需的原子操作也较少。 否则,如果状态很复杂,并且代码的不同部分在同一变量的不同条件下等待(例如,这里你想要x<10;那里你想要y>x),请使用cond_wait。 |
|
|
user107586 · 如何处理等待句柄不会导致无限循环? 1 年前 |
|
|
ron burgundy · 获取-释放语义是否跨线程传递?[副本] 1 年前 |
|
|
BenjiFB · C#内存缓存:在一次操作中追加到列表? 1 年前 |
|
|
András Takács · Python多线程问题 1 年前 |
|
|
András Takács · Python多线程错误 1 年前 |