对sleep的调用会重新加载缓存在java中的寄存器中的值吗?

问题描述 投票:1回答:2

在java规范中17.3睡眠和产量

17.3睡眠和产量

Thread.sleep导致当前正在执行的线程在指定的持续时间内休眠(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。该线程不会失去任何监视器的所有权,并且恢复执行将取决于调度和执行该线程的处理器的可用性。

值得注意的是,Thread.sleep和Thread.yield都没有任何同步语义。特别是,编译器不必在调用Thread.sleep或Thread.yield之前将寄存器中缓存的写入刷新到共享内存,编译器在调用Thread.sleep或Thread之后也不必重新加载缓存在寄存器中的值。让。

例如,在以下(损坏的)代码片段中,假设this.done是非易失性布尔字段:

while (!this.done)
    Thread.sleep(1000);

编译器可以自由地读取this.done字段一次,并在循环的每次执行中重用缓存值。这意味着循环永远不会终止,即使另一个线程改变了this.done的值

it describes that thread never reload the variable cached in registers, but when I run the following code, it doesn't work, loop terminates

public class TestDemo {

    private  static boolean  keepRunning = true;

    public static void main(String[] args)  throws Exception {
        new Thread(
            ()->{
                while (keepRunning){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {

                    }
                }
                System.out.println("loop terminates");
            }
        ).start();
        Thread.sleep(1000);
        keepRunning = false;
        System.out.println("keepRunning is false now");
    }
}

The result is :

there is something different with the code in java spec 17.3 ?

why the field keepRunning be reloaded after a call to sleep ?

    C:\Users\LuoYY\Desktop>javac TestDemo.java

    C:\Users\LuoYY\Desktop>java TestDemo
    keepRunning is false now
    loop terminates
java multithreading jvm
2个回答
1
投票

规范并未说明编译器(或运行时)必须确保该字段永远不会重新加载或与其他线程同步。

“不必”,“是免费的”,“没有任何语义”

它只表示允许这样的行为(因为它在性能优化中有意义)。

所以当涉及多个线程时,你必须明确它应该如何工作:要么使它变为volatile,要么使它成为线程局部的。


1
投票

再读一次:

“编译器可以自由阅读this.done中的字段一次”

是免费的意味着它只能读一次,或者每次都可以自行阅读。在您的情况下,它每次都会读取,这是规范允许的合法行为。

© www.soinside.com 2019 - 2024. All rights reserved.