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

时间:2011-01-20 00:07:53

标签: multithreading variables pthreads mutex conditional-statements

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

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

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

请你解释实际发生的事情。

3 个答案:

答案 0 :(得分:46)

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

本身,互斥锁不会这样做。

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

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

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

答案 1 :(得分:5)

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

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

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

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

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

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

答案 2 :(得分:5)

如果您正在寻找性能,那么请开始阅读“非阻塞/非锁定”线程同步算法。它们基于原子操作,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.