Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
onSpinWait​;()线程类的方法——Java9_Java_Multithreading_Concurrency_Java Threads_Spinlock - Fatal编程技术网

onSpinWait​;()线程类的方法——Java9

onSpinWait​;()线程类的方法——Java9,java,multithreading,concurrency,java-threads,spinlock,Java,Multithreading,Concurrency,Java Threads,Spinlock,在学习Java9特性时,我遇到了一个新的Threadclass方法,名为。根据javadocs,此方法用于: 指示呼叫方暂时无法继续,直到 其他活动中一个或多个动作的发生 有人能给我一个真实的例子或场景来帮助我理解这个方法吗?纯系统提示 我引述如下: 目标 定义一个API,允许Java代码向运行时系统提示它处于旋转循环中。API将是一个纯粹的提示,并且不包含任何语义行为要求(例如,no-op是一个有效的实现)。允许JVM受益于特定于自旋循环的行为,这些行为在某些硬件平台上可能很有用。在JDK中提

在学习Java9特性时,我遇到了一个新的
Thread
class方法,名为。根据javadocs,此方法用于:

指示呼叫方暂时无法继续,直到 其他活动中一个或多个动作的发生

有人能给我一个真实的例子或场景来帮助我理解这个方法吗?

纯系统提示

我引述如下:

目标

定义一个API,允许Java代码向运行时系统提示它处于旋转循环中。API将是一个纯粹的提示,并且不包含任何语义行为要求(例如,no-op是一个有效的实现)。允许JVM受益于特定于自旋循环的行为,这些行为在某些硬件平台上可能很有用。在JDK中提供无操作实现和内在实现,并在至少一个主要硬件平台上展示执行优势

很多时候,线程必须挂起,直到其作用域之外的内容发生更改。一种(曾经)常见的做法是
wait()notify()
模式,其中一个线程等待另一个线程唤醒它们

这有一个很大的限制,即,另一个线程必须知道可能有等待的线程,并且应该通知。如果另一个线程的工作超出了您的控制范围,则无法获得通知

唯一的办法就是旋转等待。假设您有一个检查新电子邮件并通知用户的程序:

while(true) {
    while(!newEmailArrived()) {
    }
    makeNotification();
}
这段代码每秒执行数百万次;反复旋转,使用宝贵的电力和CPU电源。一种常见的方法是在每次迭代中等待几秒钟

while(true) {
    while(!newEmailArrived()) {
        try {
            Thread.sleep(5000);
        } catch(InterruptedException e) {
        }
    }
    makeNotification();
}
这做得很好。但是,如果你必须立即工作,睡眠可能是不可能的

Java 9尝试通过引入以下新方法来解决此问题:

while(true) {
    while(!newEmailArrived()) {
        Thread.onSpinWait();
    }
    makeNotification();
}
这将与没有方法调用时完全相同,但系统可以自由降低进程优先级;当这个循环的资源需要用于其他更重要的事情时,可以减慢循环或减少循环中的电量。

它与x86操作码
暂停
相同(可能编译为),与Win32宏
YieldProcessor
、GCC的
mm\u暂停()和C方法
线程相同。SpinWait

这是一种非常弱的屈服形式:它告诉您的CPU您处于一个循环中,可能会消耗很多CPU周期等待发生某些事情(忙碌等待)

通过这种方式,CPU可以将更多资源分配给其他线程,而无需实际加载操作系统调度程序和退出准备运行的线程(这可能会很昂贵)

这种方法的一个常见用途是自旋锁,当您知道共享内存上的争用非常罕见或很快结束时,自旋锁的性能可能比普通锁更好

这类代码的伪代码可能如下所示:

int state = 0; //1 - locked, 0 - unlocked

routine lock:
    while state.cas(new_value=1, wanted_value=0) == false //if state is 0 (unlocked), store 1 (locked) and return true, otherwise just return false.
       yield

routine unlock:
    atomic_store(state,0)
yield
可以通过
Thread.onSpinWait()
实现,这意味着在尝试锁定锁时,CPU可以向其他线程提供更多资源


在实现无锁算法时,这种产生的技术非常常见和流行,因为它们大多数依赖于忙等待(这几乎总是作为原子比较和交换循环实现)。这有你能想象到的所有现实用途

在阅读了文档及其源代码之后,我只想添加我的2美分。此方法可能会触发一些优化,但可能不会-因此必须小心-您不能真正依赖它-因为这对
CPU
来说是一个
提示
,超出了需求,可能没有任何初始依赖方式。。。这意味着它的实际源代码如下所示:

@HotSpotIntrinsicCandidate
public static void onSpinWait() {}
这实际上意味着,根据一个真实示例的

,该方法在命中
JIT
中的
c2编译器之前基本上是不可操作的,
假设您希望实现异步日志记录,其中希望记录某些内容的线程不希望等待其日志消息“发布”(比如写入文件),只要它最终会发布(因为它们有真正的工作要做)

比如说,您决定拥有一个专门的使用者线程,该线程专门负责将日志消息写入文件:

(Single)Consumer

while (concurrentQueue.isEmpty())
{
    //what should I do?

}
writeToFile(concurrentQueue.popHead());
//loop
问题是如何在while块中执行?Java并没有提供理想的解决方案:您可以使用Thread.sleep(),但需要多长时间,这是很重要的;或者一个Thread.yield(),但这是未指定的,或者您可以使用锁或互斥锁*,但这通常太重,并且会降低生成程序的速度(并且会破坏异步日志记录的既定目的)

您真正想对运行时说的是,“我预计我不会等待太长时间,但我希望尽量减少等待的开销/对其他线程的负面影响”。 这就是Thread.onSpinWait()的作用

如上所述,在支持onSpinWait()的平台(如x86)上,onSpinWait()被内部化为暂停指令,这将为您带来所需的好处。因此:

(Single)Consumer

while (concurrentQueue.isEmpty())
{
    Thread.onSpinWait();

}
writeToFile(concurrentQueue.popHead());
//loop
这可以改善“忙等待”式循环的延迟

我还想澄清,它不仅在实现“自旋锁”时有用(尽管在这种情况下它肯定有用);上面的代码不需要任何类型的锁(旋转或其他)

如果你想进入杂草丛中,最好的办法莫过于


*为了清楚起见,JVM在尝试最小化互斥锁的成本方面非常聪明,最初将使用轻量级锁,但这是另一个讨论。

哦,该死的,是的!完全是我的错,读错了方向。这对我来说仍然很困惑。。。这将仅在C2编译器(也称为JIT)启动时使用。在那之前,什么都不会发生。
(Single)Consumer

while (concurrentQueue.isEmpty())
{
    Thread.onSpinWait();

}
writeToFile(concurrentQueue.popHead());
//loop