如果我们有足够的处理器来服务所有线程,Thread.yield() 会做任何事情吗?
Posted
技术标签:
【中文标题】如果我们有足够的处理器来服务所有线程,Thread.yield() 会做任何事情吗?【英文标题】:Does Thread.yield() do anything if we have enough processors to service all threads? 【发布时间】:2019-09-26 09:01:06 【问题描述】:如果我们在具有两个处理器的机器上运行两个线程并且我们在其中一个线程中调用Thread.yield()
,是否有理由认为什么都不会发生(调度程序将基本上忽略请求),因为我们有足够的处理器来服务正在运行的线程吗?
【问题讨论】:
FWIW,调用Thread.yield()
是一种温和的代码气味。这还不如打电话给sleep()
,但是当我看到它时我肯定会怀疑。它通常被用于轮询更改的线程在它们应该等待监视器、监听事件、注册异步回调等时使用。
@JohnKugelman 似乎如果涉及等待,Thread::onSpinWait
是在 java-9 中添加的。我仍然不知道该使用哪一个以及何时使用。
【参考方案1】:
每当线程调用Thread.yield()
方法时,它都会向线程调度程序提示它已准备好暂停其执行。线程调度程序可以随意忽略此提示。
如果有任何线程执行了 yield 方法,线程调度程序会检查是否有任何可运行(等待执行)的线程与该线程具有相同或更高的优先级。如果处理器发现任何具有更高或相同优先级的线程,则它将切换到新线程。如果不是,则当前线程继续执行。
因为,在您的示例中,您有足够的处理器来服务所有线程(它们正在运行,而不是在可运行状态中等待); Thread.yield()
什么都不做,你的线程会继续执行。
来自 Microsoft DOTNet 的关于 Windows 的说明:
这个方法相当于使用平台invoke调用native Win32SwitchToThread函数。
让步仅限于执行调用的处理器 线。操作系统不会将执行切换到另一个 处理器,即使该处理器处于空闲状态或正在运行 较低的优先级。如果没有其他线程准备好 在当前处理器上执行,操作系统不让步 执行
因此在某些情况下可能会有警告。
【讨论】:
在您的回答中,您没有提到可用于运行线程的处理器数量。这是怎么考虑的?具体来说,我的示例处理两个处理器和两个线程。 请注意,您的操作系统肯定会运行许多其他进程,有些可能需要 CPU 时间。 @Dave, Re, "...touch on the number of processor..." 处理器的数量不相关。Thread.yield()
,如果它做任何事情,告诉调度程序调用者 (a) 仍有工作要做,(b) 不想 放弃它正在运行的处理器,但是 ( c) 愿意 放弃处理器如果 其他线程想要它。唯一重要的处理器是调用者正在运行的处理器。唯一重要的数字是希望处理器在其上运行的其他线程的数量(具体来说,该数字是零还是大于零。)
永远不会有任何具有更高优先级的就绪线程——它们已经在运行了:)【参考方案2】:
Thread.yield()
已过时。除非您的程序要在实现 cooperative multitasking 的平台上运行或在仍然使用 green threads 的 JVM 上运行,否则调用它是没有意义的。
标准库Javadoc for Thread.yield()
实际上表明yield()
根本不需要做任何事情。
【讨论】:
我怀疑它已经过时了 - 在内部查看 jdk 类 - 它有很多用法。 写一个库,不知道跑到哪里去。【参考方案3】:我一直认为应该将 Thread::yield
替换为 Thread::onSpinWait
(从 java 9 开始)——这只是“较弱”收益率的一种形式,直到我看到 both 的用法StampedLock
:
else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
Thread.yield();
else
Thread.onSpinWait();
return 0L;
所以我不认为它已经过时了。在 jdk 源代码内部,它有很多用法,即使是相对较新的 ForkJoinPool
也有 Thread::yield
的用法。
在实践中,我只在忙碌的旋转中使用了Thread::onSpinWait
——因为至少从它的名字来看——很清楚什么时候使用它;另一方面,yield 不是 - 所以我无法确定何时以及如何使用它。
只是我的 0.02 美元。
【讨论】:
以上是关于如果我们有足够的处理器来服务所有线程,Thread.yield() 会做任何事情吗?的主要内容,如果未能解决你的问题,请参考以下文章