关于JMM中工作内存究竟什么时候同步到主存或者从主存中同步?
//1.完全死循环
new Thread(()->{
while(run){
}
System.out.println("Thead1 end");
}).start();
new Thread(()->{
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread2 set run");
run = false;
}).start();
//2.休息1ms
new Thread(()->{
while(run){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thead1 end");
}).start();
new Thread(()->{
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread2 set run");
run = false;
}).start();
在1代码中的两个线程能够复现“缺少volatile使得线程1一直循环”的问题。但是加了1ms的sleep之后(2代码),线程1中的循环就能正确马上退出。请求大佬们指点迷津。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
曾经看到过类似的问题,可以参考下https://segmentfault.com/q/1010000015787014
看过 @蓝星 的回答之后,我改进了一下测试方法,本机cpu为Intel i5-7400,win10,jdk1.8.0_211:
为了避免使用
Thread.sleep
方法造成困扰,使用循环的方式让cpu运行指定的时间:先读取再设值:
测试结果:一直循环
先设值再读取:
测试结果:总是输出loop=0,说明根本没进循环,并且线程1先退出,过大概2s后线程2退出。
在测试1的基础上在循环中加入
sleep(1)
:测试结果:输出loop=987,loop的次数在950-1050之间,说明在thread2的sleep(1000)之后thread1马上就读取到了最新值,而不是thread2线程结束后。如果sleep(2000),则总是输出loop=1,说明sleep方法结束后立马读取到正确的run值。
注意: 如果sleep函数里面的循环次数变少,还是不能退出循环。本机测试如果sleep函数中的循环次数小于29000次,则还是会一直循环下去,只要超过30000次,总是能退出循环。
在测试3的基础上,把
sleep(1)
替换为实际的for循环:测试结果:一直循环。不管 i 是多少都会一直循环。
在测试1的基础上加入synchronized语句:
测试结果:loop=45830307,能结束循环,loop次数没有意义。
在测试1的基础上加入lock.lock()语句:
测试结果:loop=55020323,能正常退出循环。
结论: