使用条件变量优于互斥锁的优点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用条件变量优于互斥锁的优点相关的知识,希望对你有一定的参考价值。

我想知道在pthreads中使用条件变量而不是互斥锁的性能优势是什么。

我发现:“没有条件变量,程序员需要让线程连续轮询(可能在关键部分),检查是否满足条件。这可能是非常消耗资源的,因为线程会持续忙于此条件变量是一种在没有轮询的情况下实现相同目标的方法。“ (https://computing.llnl.gov/tutorials/pthreads

但似乎互斥锁调用也是阻塞的(与自旋锁不同)。因此,如果线程(T1)无法获得锁定,因为某些其他线程(T2)具有锁定,则操作系统将T1置于休眠状态,并且仅在T2释放锁定并且OS给予T1锁定时才唤醒。线程T1没有真正轮询以获得锁定。从该描述中,似乎使用条件变量没有性能优势。在任何一种情况下,都不涉及民意调查。操作系统无论如何都提供了条件变量范例可以提供的好处。

你能解释一下究竟发生了什么吗?

答案

条件变量允许在该线程感兴趣的事件发生时发出信号。

互联网本身不会这样做。

如果您只需要互斥,则条件变量不会为您做任何事情。但是,如果您需要知道何时发生某些事情,那么条件变量可以提供帮助。

例如,如果您有一个要处理的项目队列,那么您将拥有一个互斥锁,以确保在由各种生产者和消费者线程访问时队列的内部是一致的。但是,当队列为空时,消费者线程如何知道什么时候它在哪里工作呢?如果没有条件变量之类的东西,则需要轮询队列,在每次轮询时获取和释放互斥锁(否则生产者线程永远不会在队列中放置某些内容)。

使用条件变量可以让消费者发现当队列为空时,它可以等待条件变量,指示队列已经放入了某些东西。没有轮询 - 该线程在生产者将某些东西放入队列之前什么也不做,然后表示队列有新项目的条件。

另一答案

你在两个独立但相关的东西中寻找太多的重叠:互斥和条件变量。

互斥锁的常见实现方法是使用标志和队列。该标志指示互斥锁是否由任何人持有(单计数信号量也可以工作),并且队列跟踪哪些线程在等待独占获取互斥锁。

然后将条件变量实现为另一个用螺栓固定到该互斥锁上的队列。排队等待获取互斥锁的线程通常一旦获得它,就可以自愿离开线路前进并进入条件队列。此时,您有两组独立的服务员:

  • 那些等待专门获得互斥的人
  • 那些等待条件变量发出信号的人

当一个持有互斥锁的线程专门发出条件变量信号时,我们现在假设它是一个单一信号(释放不超过一个等待线程)而不是广播(释放所有等待线程),第一个线程在条件变量队列被分流回到互斥队列的前端(通常)。一旦当前持有互斥锁的线程 - 通常是发出条件变量的线程 - 放弃互斥锁,互斥锁队列中的下一个线程就可以获取它。行中的下一个线程将是条件变量队列的头部。

有很多复杂的细节可以发挥作用,但这个草图应该让你感受到游戏中的结构和操作。

另一答案

如果您正在寻找性能,那么请开始阅读“非阻塞/非锁定”线程同步算法。它们基于原子操作,gcc非常友好。查找gcc原子操作。我们的测试表明,使用原子操作幅度比使用互斥锁定更快,我们可以使用多个线程增加全局值。 Here is some sample code that shows how to add items to and from a linked list from multiple threads at the same time without locking.

对于睡眠和唤醒线程,信号比条件快得多。您使用pthread_kill发送信号,并使用sigwait来休眠线程。我们也测试了同样的性能优势。 Here is some example code.

以上是关于使用条件变量优于互斥锁的优点的主要内容,如果未能解决你的问题,请参考以下文章

在无锁实现中没有互斥锁的条件变量

提升进程间共享互斥锁和提升共享互斥锁的进程间条件变量

Go36-27,28-条件变量

互斥锁,信号量,条件变量,读写锁

四十Linux 线程——线程同步之条件变量

LockSupport.java 中的 FIFO 互斥代码片段