Thread :: yield vs Thread :: onSpinWait [英] Thread::yield vs Thread::onSpinWait

查看:113
本文介绍了Thread :: yield vs Thread :: onSpinWait的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标题基本上说明了所有内容,还有我真的很想知道何时使用它们的少量补充.这可能很简单-我已经阅读了它们的文档,但仍然不能说出太多区别.

这里有这样的答案,基本上都是这样:

屈服对于忙碌的等待也很有用...

我不同意它们,原因很简单,因为 ForkJoinPool 在内部使用 Thread :: yield ,而这是jdk世界中的一个很新的功能.

真正困扰我的是jdk中的用法( StampledLock :: tryDecReaderOverflow ):

 否则if(((LockSupport.nextSecondarySeed()& OVERFLOW_YIELD_RATE)== 0)Thread.yield();别的Thread.onSpinWait();返回0L; 

因此,似乎在某些情况下,一个优先于另一个.而且,不,我没有实际的示例可能需要使用它-我实际使用的唯一示例是 Thread :: onSpinWait ,因为1)我碰巧忙于等待2)名称非常多自我说明,我应该在忙碌的旋转中使用过它.

解决方案

阻止线程时,有几种策略可供选择:spin, wait()/ notify(),或两者结合.对变量进行纯旋转是一种非常低的延迟策略,但是它可能会使其他争夺CPU时间的线程饿死.另一方面, wait()/ notify()将为其他线程释放CPU,但在对线程进行调度时可能会花费数千个CPU周期的延迟./p>

那么如何避免纯旋转以及与调度和调度阻塞线程相关的开销?

Thread.yield()是对线程调度程序的提示,如果准备好另一个具有相同或更高优先级的线程,则放弃它的时间片.这样可以避免纯粹的自旋,但不能避免重新安排线程的开销.

最新添加的内容是 Thread.onSpinWait(),它插入特定于体系结构的指令以提示处理器线程处于自旋循环中.在x86上,这可能是 PAUSE 指令,在aarch64上,这是 YIELD 指令.

这些说明的用途是什么?在纯自旋循环中,处理器将一次又一次地推测性地执行循环,从而填满管道.当线程旋转的变量最终改变时,由于违反内存顺序,所有的推测性工作都将被丢弃.真是浪费!

给处理器的提示可能会阻止流水线推测性地执行自旋循环,直到提交了先前的存储器指令为止.在SMT(超线程)的情况下,这很有用,因为可以为其他硬件线程释放管道.

Well the title basically says it all, with the small addition that I would really like to know when to use them. And it might be simple enough - I've read the documentation for them both, still can't tell the difference much.

There are answers like this here that basically say:

Yielding also was useful for busy waiting...

I can't agree much with them for the simple reason that ForkJoinPool uses Thread::yield internally and that is a pretty recent addition in the jdk world.

The thing that really bothers me is usages like this in jdk too (StampledLock::tryDecReaderOverflow):

    else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
        Thread.yield();
    else
        Thread.onSpinWait();
    return 0L;

So it seems there are cases when one would be preferred over the other. And no, I don't have an actual example where I might need this - the only one I actually used was Thread::onSpinWait because 1) I happened to busy wait 2) the name is pretty much self explanatory that I should have used it in the busy spin.

解决方案

When blocking a thread, there are a few strategies to choose from: spin, wait() / notify(), or a combination of both. Pure spinning on a variable is a very low latency strategy but it can starve other threads that are contending for CPU time. On the other hand, wait() / notify() will free up the CPU for other threads but can cost thousands of CPU cycles in latency when descheduling/scheduling threads.

So how can we avoid pure spinning as well as the overhead associated with descheduling and scheduling the blocked thread?

Thread.yield() is a hint to the thread scheduler to give up its time slice if another thread with equal or higher priority is ready. This avoids pure spinning but doesn't avoid the overhead of rescheduling the thread.

The latest addition is Thread.onSpinWait() which inserts architecture-specific instructions to hint the processor that a thread is in a spin loop. On x86, this is probably the PAUSE instruction, on aarch64, this is the YIELD instruction.

What's the use of these instructions? In a pure spin loop, the processor will speculatively execute the loop over and over again, filling up the pipeline. When the variable the thread is spinning on finally changes, all that speculative work will be thrown out due to memory order violation. What a waste!

A hint to the processor could prevent the pipeline from speculatively executing the spin loop until prior memory instructions are committed. In the context of SMT (hyperthreading), this is useful as the pipeline will be freed up for other hardware threads.

这篇关于Thread :: yield vs Thread :: onSpinWait的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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