Eug*_*ene 8 java concurrency java.util.concurrent
好吧,标题基本上说明了一切,还有我真的很想知道何时使用它们的少量补充。可能很简单-我已经阅读了它们的文档,但仍然不能说出太多区别。
有喜欢回答这个位置,基本上说:
屈服对于忙碌的等待也很有用...
我不太同意他们的说法,原因很简单,即内部ForkJoinPool使用Thread::yield,这是jdk世界中的新增功能。
真正困扰我的是jdk中的用法(StampledLock::tryDecReaderOverflow):
else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
Thread.yield();
else
Thread.onSpinWait();
return 0L;
Run Code Online (Sandbox Code Playgroud)
因此,似乎在某些情况下,一个会比另一个更受欢迎。而且,没有,我没有实际的示例可能需要使用它-我实际使用的唯一示例是Thread::onSpinWait因为1)我碰巧忙于等待2)这个名字很能说明我应该在忙碌中使用它旋转。
阻塞线程时,有几种策略可供选择:spin,wait()/ notify()或两者的组合。对变量进行纯旋转是一种非常低的延迟策略,但是它可能会使其他竞争CPU时间的线程饿死。另一方面,wait()/ notify()将为其他线程释放CPU,但在对线程进行调度时可能会花费数千个CPU周期的延迟。
那么,如何避免纯旋转以及与调度和调度阻塞线程相关的开销呢?
Thread.yield()如果另一个具有相同或更高优先级的线程准备就绪,则向线程调度程序提供提示,以放弃其时间片。这样可以避免纯粹的自旋,但不能避免重新安排线程的开销。
最新的功能是Thread.onSpinWait()插入特定于体系结构的指令,以提示处理器线程处于自旋循环中。在x86上,这可能是PAUSE指令,在aarch64上,这是YIELD指令。
这些说明有什么用?在纯自旋循环中,处理器将一次又一次地推测性地执行循环,以填满管道。当线程旋转的变量最终改变时,由于违反内存顺序,所有的推测性工作将被丢弃。真是浪费!
给处理器的提示可能会阻止流水线推测性执行自旋循环,直到提交了先前的内存指令为止。在SMT(超线程)的上下文中,这很有用,因为可以为其他硬件线程释放管道。
| 归档时间: |
|
| 查看次数: |
177 次 |
| 最近记录: |