并发之可见性
第一种情况:while空循环,永远无法获得主线程修改过的变量值
@Slf4j
public class TestVisibility {
private static boolean run = true;
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(()->{
TestVisibility.m();
});
t1.start();
Thread.sleep(1000);
run = false;
Thread.sleep(1000);
System.out.println(t1.isAlive());
}
public static void m() {
log.info("in");
while(run) {
}
log.info("out");
}
}
运行结果

第二种情况:while循环里面执行log.info(“running”),t1线程会获得主线程中对run变量的修改,t1线程会执行完毕
@Slf4j
public class TestVisibility {
private static boolean run = true;
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(()->{
TestVisibility.m();
});
t1.start();
Thread.sleep(1000);
run = false;
Thread.sleep(1000);
System.out.println(t1.isAlive());
}
public static void m() {
log.info("in");
while(run) {
log.info("running");
}
log.info("out");
}
}
运行结果

原因
- JVM会尽可能去保证内存的可见性,while进行空循环的时候会一直占用CPU,所以CPU没有时间去获取run的最新值,就会一直运行;
- 当在while循环里面进行打印的时候,CPU会有一点点点点的空闲时间,这个时候CPU去会去主存里面获取run的最新值,t1线程发现run
= false的时候就会退出循环,t1线程就会正常停止
本文通过两个示例探讨了Java并发中的可见性问题。在第一个例子中,一个线程在空循环中无法感知主线程对共享变量的修改,而第二个例子中,循环内的日志打印使得线程能够捕获到变量的更新。这展示了JVM虽然尽力保证内存可见性,但在特定情况下CPU可能因高负载而无法及时获取最新值。理解这种现象对于优化并发代码和避免死锁至关重要。
909

被折叠的 条评论
为什么被折叠?



