条件变量与信号量 [英] Conditional Variable vs Semaphore

查看:264
本文介绍了条件变量与信号量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

何时应使用信号量,何时应使用条件变量(CondVar)?

When should one use a semaphore and when should one use a conditional variable (CondVar) ?

推荐答案

锁用于互斥.当您想要确保一段代码是原子的时,请在其周围加一个锁.从理论上讲,您可以使用二进制信号量来执行此操作,但这是一种特殊情况.

Locks are used for mutual exclusion. When you want to ensure that a piece of code is atomic, put a lock around it. You could theoretically use a binary semaphore to do this, but that's a special case.

信号量和条件变量建立在锁提供的互斥之上,用于提供对共享资源的同步访问.它们可以用于类似目的.

Semaphores and condition variables build on top of the mutual exclusion provide by locks and are used for providing synchronized access to shared resources. They can be used for similar purposes.

通常使用条件变量来避免在等待资源可用时的繁忙等待(在检查条件时反复循环).例如,如果您有一个(或多个)线程在队列为空之前无法继续运行,那么繁忙的等待方法将是执行以下操作:

A condition variable is generally used to avoid busy waiting (looping repeatedly while checking a condition) while waiting for a resource to become available. For instance, if you have a thread (or multiple threads) that can't continue onward until a queue is empty, the busy waiting approach would be to just doing something like:

//pseudocode
while(!queue.empty())
{
   sleep(1);
}

与此有关的问题是,通过让该线程反复检查条件,您正在浪费处理器时间.为什么不使用一个同步变量来通知线程该资源可用呢?

The problem with this is that you're wasting processor time by having this thread repeatedly check the condition. Why not instead have a synchronization variable that can be signaled to tell the thread that the resource is available?

//pseudocode
syncVar.lock.acquire();

while(!queue.empty())
{
   syncVar.wait();
}

//do stuff with queue

syncVar.lock.release();

大概,您将在其他地方有一个线程将事情拖出队列.当队列为空时,它可以调用syncVar.signal()来唤醒在syncVar.wait()上处于睡眠状态的随机线程(或者通常还有一个signalAll()broadcast()方法来唤醒所有正在等待的线程)

Presumably, you'll have a thread somewhere else that is pulling things out of the queue. When the queue is empty, it can call syncVar.signal() to wake up a random thread that is sitting asleep on syncVar.wait() (or there's usually also a signalAll() or broadcast() method to wake up all the threads that are waiting).

当我有一个或多个线程在单个特定条件下等待时(例如,队列为空),我通常使用这样的同步变量.

I generally use synchronization variables like this when I have one or more threads waiting on a single particular condition (e.g. for the queue to be empty).

信号量可以类似地使用,但是我认为当您拥有一个共享资源时,基于一些可用事物的整数,它们可以更好地使用.信号量适用于生产者/消费者的情况,生产者正在分配资源而消费者正在消耗它们.

Semaphores can be used similarly, but I think they're better used when you have a shared resource that can be available and unavailable based on some integer number of available things. Semaphores are good for producer/consumer situations where producers are allocating resources and consumers are consuming them.

考虑一下您是否有汽水自动售货机.只有一台汽水机,这是一种共享资源.您有一个线程是供应商(生产者),负责保持机器的库存,有N个线程是买家(消费者),他们希望从机器中取出苏打水.机器中的苏打水数量是整数,它将驱动我们的信号量.

Think about if you had a soda vending machine. There's only one soda machine and it's a shared resource. You have one thread that's a vendor (producer) who is responsible for keeping the machine stocked and N threads that are buyers (consumers) who want to get sodas out of the machine. The number of sodas in the machine is the integer value that will drive our semaphore.

苏打水机器上的每个购买者(消费者)线程都会调用信号量down()方法来获取苏打水.这将从机器中获取苏打,并将可用苏打的数量减少1.如果有可用苏打,则代码将一直运行通过down()语句而不会出现问题.如果没有可用的苏打水,线程将在此处休眠,等待再次提供苏打水时(机器中有更多苏打水时)得到通知.

Every buyer (consumer) thread that comes to the soda machine calls the semaphore down() method to take a soda. This will grab a soda from the machine and decrement the count of available sodas by 1. If there are sodas available, the code will just keep running past the down() statement without a problem. If no sodas are available, the thread will sleep here waiting to be notified of when soda is made available again (when there are more sodas in the machine).

供应商(生产者)线程实际上将在等待苏打水机器为空.当从机器中取出最后的苏打水时,供应商会收到通知(并且一个或多个消费者可能正在等待将苏打水取出).供应商将使用信号量up()方法对苏打水机器进行重新库存,每次苏打水的可用数量都会增加,因此正在等待的消费者线程将得到更多苏打水可用的通知.

The vendor (producer) thread would essentially be waiting for the soda machine to be empty. The vendor gets notified when the last soda is taken from the machine (and one or more consumers are potentially waiting to get sodas out). The vendor would restock the soda machine with the semaphore up() method, the available number of sodas would be incremented each time and thereby the waiting consumer threads would get notified that more soda is available.

同步变量的wait()signal()方法倾向于隐藏在信号量的down()up()操作中.

The wait() and signal() methods of a synchronization variable tend to be hidden within the down() and up() operations of the semaphore.

当然,这两个选择之间存在重叠.在许多情况下,信号量或条件变量(或条件变量集)都可以满足您的目的.信号量和条件变量都与用于保持互斥的锁对象相关联,但随后它们在锁的顶部提供了用于同步线程执行的额外功能.由您自己决定哪种情况最适合您的情况.

Certainly there's overlap between the two choices. There are many scenarios where a semaphore or a condition variable (or set of condition variables) could both serve your purposes. Both semaphores and condition variables are associated with a lock object that they use to maintain mutual exclusion, but then they provide extra functionality on top of the lock for synchronizing thread execution. It's mostly up to you to figure out which one makes the most sense for your situation.

这不一定是最具技术性的描述,但这就是我的脑筋.

That's not necessarily the most technical description, but that's how it makes sense in my head.

这篇关于条件变量与信号量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆