volatile
2021-08-22 本文已影响0人
张某某xyz
20210822
保证可见性、不保证原子性、防止指令重排
保证可见性
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改后的值
public class VolatileTest {
private static boolean b = false;
public static void main(String[] args) {
new Thread(() -> {
while (true) {
// 永远不会进入这个if,线程t2将b改成了true,但是线程t1看不见
// 解决:用volatile修饰b
if (b) break;
}
}, "t1").start();
new Thread(() -> {
MyThreadUtil.sleepSeconds(1);
b = true;
}, "t2").start();
}
}
以下是进阶
为什么可以保证可见性
JMM(Java memory model)规定每个线程使用共享变量时都将该变量拷贝一份到自己的缓存(即虚拟机栈)
多个线程都缓存共享变量时,就有缓存一致性问题(即可见性问题,一个线程不可见另一个线程对共享变量的修改),JMM的解决是:

read、load、use必须连续出现
assign、store、write必须连续出现
这样当修改变量时,就会assign=>store=>write将新值刷到主存;使用时是read=>load=>use 所以用的是最新值
为什么可以防止指令重排
因为内存屏障
如果面试官还深问,就说volatile的C++源码中
locked;addl...
起到内存屏障作用,就是该句代码保证的可见性和防止指令重排
![]()