条件变量,互斥锁和锁之间的差异

Ron*_*del 47 c++ multithreading mutex condition-variable c++11

例如c ++ 0x接口

我很难搞清楚何时使用这些东西(简称cv,互斥锁和锁).任何人都可以解释或指向一个资源?

提前致谢.

Ant*_*ima 68

在您引用的页面上,"mutex"是实际的低级同步原语.您可以使用互斥锁然后释放它,并且只有一个线程可以在任何时候使用它(因此它是同步原语).递归互斥锁是一个可以被同一个线程多次占用的互斥锁,然后它需要被同一个线程释放多次,然后其他人才能接受它.

这里的"锁"只是一个C++包装类,它在构造函数中使用互斥锁并在析构函数中释放它.它对于为C++范围建立同步很有用.

条件变量是更高级/高级形式的同步原语,它将锁与"信令"机制相结合.当线程需要等待资源变得可用时使用它.线程可以在CV上"等待",然后资源生成器可以"发出信号"该变量,在这种情况下,等待CV的线程会得到通知并可以继续执行.将互斥锁与CV组合以避免竞争条件,其中线程开始在CV上等待另一个线程想要发信号; 那么信号是否被传递或丢失是不可控制的.

  • @hydroes:没有.如果thread1正在等待一个锁,那么一些其他线程必须持有它以使thread1保持阻塞状态.一旦其他线程释放它,thread1可以解除阻塞以获取互斥锁.使用条件变量,任何线程都可以发出信号以解除对服务员的阻塞,而不仅仅是一直持有锁的特殊线程.此外,您可以广播条件变量,以释放所有等待的线程. (20认同)
  • 是不是等待(thread1)+信令(thread2)与convars,完全一样的锁定(thread1)+解锁(thread2)? (3认同)

Ali*_*asi 6

这个问题已经得到解答。我只是添加了这一点,这可能有助于决定何时使用这些同步原语。

简单来说,互斥量是用来保证多个线程对临界区共享资源的相互访问。运气是一个通用术语,但二进制互斥体可以用作锁。在现代 C++ 中,我们使用 lock_guard 和类似对象来利用 RAII 来简化互斥体的使用并使其安全。条件变量是另一个原语,通常与互斥体结合使用,使某些东西称为监视器

我很难弄清楚何时使用这些东西(cv、互斥锁和锁)。任何人都可以解释或指出资源吗?

使用互斥锁来保证对某些内容的互斥访问。它是多种并发问题的默认解决方案。如果您在 C++ 中有一个作用域并希望使用互斥体来保护它,请使用 lock_guard。互斥体由lock_guard 处理。您只需在作用域中创建一个 lock_guard 并使用互斥锁对其进行初始化,然后 C++ 会为您完成其余的工作。当由于任何原因(包括引发异常或从函数返回)从堆栈中删除作用域时,互斥体将被释放。这是RAII背后的想法,lock_guard 是另一个资源处理程序。

有些并发问题仅通过互斥体无法轻松解决,或者简单的解决方案可能会导致复杂性或效率低下。例如,生产者-消费者问题就是其中之一。如果我们想要实现一个消费者线程从与生产者共享的缓冲区中读取项目,我们应该使用互斥体保护缓冲区,但是,如果不使用条件变量,我们应该锁定互斥体,检查缓冲区并读取项目(如果它不为空) ,解锁并等待一段时间,再次锁定并继续。如果缓冲区经常为空(忙于等待),那么就会浪费时间,而且还会有大量的锁定、解锁和睡眠。

我们需要的生产者-消费者问题的解决方案必须更简单、更高效。监视器(互斥锁+条件变量)可以帮助我们。我们仍然需要一个互斥锁来保证互斥访问,但是条件变量让我们可以休眠并等待某个条件。这里的条件是生产者向缓冲区添加一个项目。生产者线程通知消费者线程缓冲区中有项目,消费者醒来并获取该项目。简单地说,生产者锁定互斥体,将某些内容放入缓冲区,通知消费者。消费者锁定互斥体,在等待条件时休眠,当缓冲区中有东西时唤醒并从缓冲区中获取该项目。这是一个更简单、更有效的解决方案。

下次遇到并发问题时,请这样想:如果需要对某些内容进行互斥访问,请使用互斥体。如果你想更安全、更简单,请使用lock_guard。如果问题有等待另一个线程中必须发生的条件的线索,您可能需要一个条件变量。

作为一般经验法则,首先,分析您的问题并尝试找到与您的问题类似的著名并发问题(例如,请参阅本页中同步部分的经典问题)。了解针对众所周知的解决方案提出的解决方案,以达到最佳解决方案的峰值。您可能需要一些定制。


Jas*_*n S 5

我不太熟悉w/C++ 0x所以拿这个答案w/gra.

re:Mutex vs. locks:从您发布的文档中,它看起来像是mutex表示OS互斥体lock的对象,而a 是保存互斥体以促进RAII模式的对象.

条件变量是一种将阻塞/信令机制(信号+等待)与互斥机制相关联的便捷机制,但是它们在操作系统中保持解耦,以便您作为系统程序员可以选择condvar和互斥锁之间的关联.(对于处理多组并发访问的对象很有用)Rob Krten在他关于QNX的书的一个在线章节中对condvars有一些很好的解释.

至于一般参考:这本书(尚未出版)看起来很有趣.