为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

青春有我 2022-08-03 12:36:19
在 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
查看完整描述

2 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

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

“不必”,“自由”,“没有任何语义”

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

因此,当涉及多个线程时,您必须明确说明它应该如何工作:要么使其易失性,要么使其成为线程本地线程。


查看完整回答
反对 回复 2022-08-03
?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

再读一遍:

“编译器可以自由读取这个字段,只需完成一次”

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


查看完整回答
反对 回复 2022-08-03
  • 2 回答
  • 0 关注
  • 126 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号