多线程,何时屈服与睡眠

问题描述 投票:12回答:4

为了澄清术语,yield是线程放弃时间片的时间。我感兴趣的平台是POSIX线程,但我认为这个问题很普遍。

假设我有消费者/生产者模式。如果我想扼杀消费者或生产者,哪个更好用,睡觉还是产量?我最感兴趣的是使用这两种功能的效率。

multithreading sleep yield
4个回答
10
投票

对生产者/消费者进行编码的“正确”方法是让消费者等待生产者的数据。您可以使用同步对象(如Mutex)来实现此目的。消费者将在互斥锁上使用Wait,阻止它执行直到数据可用。反过来,生产者将在数据可用时发出互斥信号,这将唤醒消费者线程,以便开始处理。就两者而言,这比sleep更有效:

  • CPU利用率(没有浪费周期),以及
  • 运行时间(数据可用时立即开始执行,而不是在计划唤醒线程时执行)。

也就是说,这是你要求的产量与睡眠的分析。如果由于某种原因等待输出不可行,您可能需要使用这样的方案:

这取决于您接收的流量 - 如果不断收到和处理数据,您可能会考虑收益。然而,在大多数情况下,这将导致“忙”循环,其大部分时间花费在不必要地唤醒线程以检查是否有任何准备好。

你可能想要在短时间内睡觉(可能不到一秒钟,使用usleep)或者甚至更好地使用同步对象(如互斥锁)来表示数据可用。


10
投票

睡眠和产量都不一样。当调用sleep时,进程/线程在给定的时间内将CPU提供给另一个进程/线程。

yield将CPU释放到另一个线程,但如果没有其他线程等待CPU,则可能会立即返回。

因此,如果您想节流,例如在定期流式传输数据时,则需要使用睡眠或nanosleep功能。

如果需要生产者/消费者之间的同步,则应使用互斥/条件等待。


1
投票

睡觉而不是屈服的一个好理由是在特定关键部分存在太多争用时。让我们说比如说你试图获得两个锁,并且两个锁都有很多争用。在这里你可以使用睡眠来使用指数退避。这将允许每次失败尝试伪随机退回以允许其他线程成功。

在这种情况下屈服并没有多大帮助,因为随机退避的可能性会增加线程饥饿不会发生的可能性。

编辑:虽然我知道这不一定是java特定的。 Java对Thread.sleep(0)的实现具有与Thread.yield()相同的效果。在这一点上,它更多地是一种风格问题。


0
投票

在java中,一些JVM实现将Thread.yield()视为no-op,这意味着它可能没有任何效果。调用Thread.sleep()并不一定意味着调度程序应该将CPU输出到另一个线程;这也是依赖于实现的。它可以上下文切换到正在等待的另一个线程,或者可能不是为了分摊与上下文切换相关联的成本。

© www.soinside.com 2019 - 2024. All rights reserved.