关于JUC的技术疑问:线程变量可见性及volatile应用探讨
Java并发可见性问题解答
示例代码
public class TestJUC { private int x; public void actor1(){ x = 1; } public void actor2() { System.out.println(x); } }
问题与解答
问题1:线程A执行actor1方法,线程B执行actor2方法,且线程A在线程B启动前已完成x=1的赋值操作,线程B是否必然输出1?
线程B不一定会输出1。在无同步机制的情况下,Java内存模型(JMM)不保证线程A对x的写入操作能被线程B可见。即便代码逻辑上A先完成赋值,编译器或CPU可能对指令重排序,或者因缓存一致性延迟,线程B仍可能读取到x的初始值0。
问题2:是否会因CPU的StoreBuffer与Invalidate Queue存在可见性问题?若存在该可见性问题,是否需要用volatile修饰变量x?
确实会由此引发可见性问题:
- Store Buffer:CPU为提升性能,会先将写入操作暂存到Store Buffer,而非立即刷新到主内存,此时其他CPU核心缓存中的x仍是旧值。
- Invalidate Queue:通知其他核心缓存失效的指令可能被放入队列延迟处理,导致其他核心无法及时感知x的更新。
这种场景下需要用volatile修饰变量x,原因如下:
- 禁止编译器和CPU对该变量相关指令进行重排序;
- 强制将变量写入操作立即刷新至主内存;
- 读取时直接从主内存加载,同时使其他核心缓存中的该变量副本失效,避免读取旧值。
内容的提问来源于stack exchange,提问作者qwee
相关产品推荐
相关产品推荐

