我确信互斥锁还不够,这就是条件变量概念存在的原因;但这让我很困惑,当条件变量至关重要时,我无法用具体的场景说服自己。
条件变量、互斥锁和锁之间的区别问题的接受答案说条件变量是
带有“信号”机制的锁。当线程需要时使用它
等待资源变得可用。线程可以在 CV 上“等待”
然后资源生产者可以向变量发出“信号”,其中
如果等待 CV 的线程收到通知并可以继续
执行
我感到困惑的是,线程也可以等待互斥锁,当它收到信号时,仅仅意味着该变量现在可用,为什么我需要条件变量?
P.S.:此外,无论如何,都需要互斥锁来保护条件变量,这会让我的视野更加偏向于看不到条件变量的用途。
尽管您可以按照您所描述的方式使用它们,但互斥体并不是设计用作通知/同步机制。它们旨在提供对共享资源的互斥访问。使用互斥体来发出条件信号是很尴尬的,我想看起来像这样(其中 Thread1 由 Thread2 发出信号):
Thread1:
while(1) {
lock(mutex); // Blocks waiting for notification from Thread2
... // do work after notification is received
unlock(mutex); // Tells Thread2 we are done
}
Thread2:
while(1) {
... // do the work that precedes notification
unlock(mutex); // unblocks Thread1
lock(mutex); // lock the mutex so Thread1 will block again
}
这有几个问题:
- 线程 2 无法继续“执行通知之前的工作”,直到线程 1 完成“通知之后的工作”。通过这种设计,Thread2 甚至没有必要,也就是说,为什么不将“之前的工作”和“通知之后的工作”移到同一个线程中,因为在给定时间只有一个可以运行!
- 如果 Thread2 无法抢占 Thread1,则 Thread1 在重复 while(1) 循环时将立即重新锁定互斥锁,并且 Thread1 将继续执行“通知后的工作”,即使没有通知。这意味着您必须以某种方式保证 Thread2 将在 Thread1 之前锁定互斥体。你是怎样做的?也许通过睡眠或其他一些特定于操作系统的方式强制调度事件,但即使这样也不能保证有效,具体取决于时间、操作系统和调度算法。
这两个问题都不是小问题,事实上,它们都是主要的设计缺陷和潜在的错误。这两个问题的根源在于互斥体需要在同一线程内锁定和解锁。那么如何避免上述问题呢?使用条件变量!
顺便说一句,如果您的同步需求非常简单,您可以使用普通的旧信号量,这样可以避免条件变量的额外复杂性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)