为了澄清术语,yield是线程放弃时间片的时间。 我感兴趣的平台是POSIX线程,但我认为这个问题很普遍。
假设我有消费者/生产者模式。如果我想扼杀消费者或生产者,哪个更好用,睡觉还是产量?我最感兴趣的是使用这两种功能的效率。
答案 0 :(得分:10)
对生产者/消费者进行编码的“正确”方法是让消费者等待生产者的数据。您可以使用同步对象(如Mutex)来实现此目的。消费者将在互斥锁上Wait
,阻止它执行直到数据可用。反过来,生产者将在数据可用时发出互斥信号,这将唤醒消费者线程,以便开始处理。就两者而言,这比sleep
更有效:
那就是说,这是你要求的产量与睡眠的分析。如果由于某种原因等待输出不可行,您可能需要使用这样的方案:
这取决于您接收的流量 - 如果不断收到和处理数据,您可能会考虑收益。然而,在大多数情况下,这将导致“忙”循环,其大部分时间花费在不必要地唤醒线程以检查是否有任何准备好。
您可能希望在短时间内睡眠(可能不到一秒,使用usleep
)或者甚至更好地使用同步对象(如互斥锁)来表示数据可用。< / p>
答案 1 :(得分:10)
yield将CPU放弃到另一个线程,但如果没有其他线程等待CPU,则可能立即返回。
因此,如果你想节流,例如定期流式传输数据,那么睡眠或纳米睡眠是要使用的功能。
如果需要生产者/消费者之间的同步,则应使用互斥/条件等待。
答案 2 :(得分:1)
睡眠而不是屈服的一个好理由是在特定关键部分存在太多争用。让我们说比如说你试图获得两个锁,并且两个锁都有很多争用。在这里你可以使用睡眠来使用指数退避。这将允许每次失败尝试伪随机退回以允许其他线程成功。
在这种情况下屈服并没有多大帮助,因为随机退避的可能性会增加线程饥饿不会发生的可能性。
编辑:虽然我知道这不一定是特定于java的。 Java Thread.sleep(0)
的实现与Thread.yield()
具有相同的效果。在这一点上,它更多地是一种风格问题。
答案 3 :(得分:0)
在java中,一些JVM实现将Thread.yield()视为no-op,这意味着它可能没有任何效果。调用Thread.sleep()并不一定意味着调度程序应该将CPU输出到另一个线程;这也是依赖于实现的。它可以上下文切换到正在等待的另一个线程,或者可能不是为了分摊与上下文切换相关联的成本。