关于可见性大家还有误区的问题 Thread.sleep对其的影响讨论
对于学习可见性,我们应该都看过下面这样的代码,很简单的
public class VisibilityTest {
Integer a = 0;
public static void main(String[] args) throws InterruptedException {
VisibilityTest test = new VisibilityTest();
test.testVisibility();
}
public void testVisibility() {
new Thread(() -> {
System.out.println("thread 1 start ======= a =" + this.a);
while (this.a != 10) {
}
System.out.println("thred 1 a =======" + this.a);
System.out.println("thread 1 end =======");
}).start();
try {
Thread.sleep(1000L);
// TimeUnit.NANOSECONDS.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
System.out.println("thread 2 modify ....");
this.a = 10;
System.out.println("thread 2 modify success a = " + this.a);
}).start();
}
}
上面这个代码大概率的运行结果会是这样的:
thread 1 start ======= a =0
thread 2 modify ....
thread 2 modify success a = 10
然后main方法一直停止不掉;
那如果我们将Thread.sleep()这个去掉了,即使线程1先运行,但程序依然会执行成功;
public void testVisibility() {
new Thread(() -> {
System.out.println("thread 1 start ======= a =" + this.a);
while (this.a != 10) {
}
System.out.println("thred 1 a =======" + this.a);
System.out.println("thread 1 end =======");
}).start();
new Thread(() -> {
System.out.println("thread 2 modify ....");
this.a = 10;
System.out.println("thread 2 modify success a = " + this.a);
}).start();
}
thread 1 start ======= a =0
thread 2 modify ....
thread 2 modify success a = 10
thred 1 a =======10
thread 1 end =======
那这跟我们所了解的可见性好像有点区别啊?
为什么Thread.sleep()会影响到主内存中的值刷新到线程1中的工作内存中去了?因为线程2运行完了,它会通过原子操作将以前进行assign的值,通过store,write这些原子操作设置到主内存中去;但我加了Thread.sleep(1000L)这行代码时,我运行main方法,程序会等很久,线程1不会完成(也即线程1的工作内存副本一直没有获取到主内存中的最新值);但是我不加这行代码,线程1即使比线程2先运行,它也会很快的刷新到主内存中的值;
那么带着这个疑问,我将方法体中Thread.sleep(1000L)改成了TimeUnit.NANOSECONDS.sleep(1); 我让主线程休眠1纳秒;这时,我测试j时,跟方法体中不加这行代码一样,线程1也会很快的读取到主内存中的值;
上面这些测试都是在windows系统中测试的;由些可见,Thread.sleep会影响主内存与工作副本中的值的刷新时间,而且影响有点大;不知道有相关了解的大佬们能给个合理的解释不?
相关推荐
JAVA工程师面试测试附答案
JAVA工程师面试测试附答案
Windows进程可见性控制原理与工程实践
进程可见性是Windows系统安全与管理的基础概念,其核心在于对象管理器(Object Manager)对EPROCESS结构体的枚举与访问控制。理解Psapi、Toolhelp32等API的底层差异,掌握用户态隔离(如CreateProcessAsUser+空桌面)与内核态过滤(ObRegisterCallbacks)的技术原理,有助于构建稳定、合规的进程保护机制。该技术在金融终端防注入、工业软件防误终止等合法场景中具备明确工程价值,但需严格遵循最小权限、用户授权与可审计原则。本文聚焦C++驱动开发视角下
【工业自动化】欧姆龙PLC产品线与编程软件应用:从选型架构到调试排错的全流程技术指南
内容概要:本文《欧姆龙PLC与编程软件完全手册》系统介绍了欧姆龙PLC的产品架构、软件体系、通信协议、选型策略及编程调试技巧。重点区分了两大技术平台:基于CX-Programmer的传统C系列(CP/CJ/CS)与基于Sysmac Studio的新一代Sysmac平台(NJ/NX/NY),强调二者在软件生态、寻址方式和通信架构上的根本差异。手册详细对比了各系列PLC的性能参数,并提供与西门子产品的功能对标,帮助用户快速定位。深入讲解了编程操作中的关键问题,如任务结构设计、间接寻址、FB封装陷阱、在线调试五件套等,特别指出“FB使能关闭时状态不初始化”等易出错点。最后汇总了选型路径与现场避坑清单,极具实战指导价值。; 适合人群:具备一定工业自动化基础,从事PLC编程、设备调试、系统集成的研发工程师和技术人员,尤其是从西门子平台转向欧姆龙或参与新项目选型的1-5年经验从业者。; 使用场景及目标:① 新项目选型时判断应选用C系列还是Sysmac平台;② 编程调试过程中掌握高效操作技巧与常见问题排查方法;③ 实现跨平台迁移、系统升级或接手他人项目时规避架构与逻辑陷阱;④ 提升对欧姆龙PLC任务机制、间接寻址、FB设计等高级功能的理解与应用能力。; 阅读建议:本手册理论结合实践,建议按“先架构后操作”的顺序阅读,重点章节需结合实际工程反复演练。特别是FB设计规范、任务切换处理、强制操作收尾流程等内容,应在仿真环境中验证后再应用于现场。注意版本匹配问题,操作前确认所用软件与控制器固件版本兼容。
CISP-CSE注册云安全工程师备考资源包
CISP-CSE注册云安全工程师备考资源包
科技中介服务机构如何通过AI技术降低技术评估与匹配服务的操作门槛?.docx
科技中介服务机构如何通过AI技术降低技术评估与匹配服务的操作门槛?


Java SE
