对睡眠的调用将重新加载缓存在java寄存器中的值?

在 java 规范 17.3 中 睡眠和产量

17.3 睡眠和产量


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


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


例如,在下面(断开的)代码片段中,假定 this.done 是一个非易失性布尔字段:


while (!this.done)

    Thread.sleep(1000);

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


它描述了线程从不重新加载寄存器中缓存的变量,但是当我运行以下代码时,它不起作用,循环终止

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");

    }

}

结果是:

java规范17.3中的代码有一些不同之处?

为什么字段 keepRunning 在调用睡眠后重新加载?

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


    C:\Users\LuoYY\Desktop>java TestDemo

    keepRunning is false now

    loop terminates


青春有我
浏览 127回答 2
2回答

牛魔王的故事

规范没有说编译器(或运行时)必须确保该字段永远不会被重新加载或与其他线程同步。“不必”,“自由”,“没有任何语义”它只说允许这样的行为(因为它在性能优化中是有意义的)。因此,当涉及多个线程时,您必须明确说明它应该如何工作:要么使其易失性,要么使其成为线程本地线程。

米琪卡哇伊

再读一遍:“编译器可以自由读取这个字段,只需完成一次”是免费的,这意味着它可以只阅读一次,或者每次都可以自行决定阅读它。在您的情况下,它每次都会读取,这是规范允许的合法行为。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java