一.可见性问题
1.CPU指令重排
Java编程语言为了增强效率,其的语义允许Java编译器和微处理器进行执行优化,
这些优化导致了与其交互的代码不再同步,从而导致出现看似矛盾的行为。
比如代码
boolean isTrue = true;
while (isTrue){
//...
}
在循环判断执行一定次数,变量isTrue的值一直为true,则CPU就会将该代码进行指令重排
boolean isTrue = true;
if (isTrue) {
//...
}
变成if(true),这样在变量isTrue的值被更改后,还是不会出现
又比如代码如果在多线程的情况下
//线程A
int a = 10;
a = 20;
boolean flag = true;
线程B中的代码
//线程B
while(flag){
System.out.println(a);
}
如果指令重排将flag赋值true指令重排在 a = 20之前的话,输出的结果就会不一样了
2.CPU高速缓存
线程与主内存进行交互,中间还有层CPU高速缓存,而这段进出高速缓存期间也有极小的可能出现数据不一致的问题
二.volatile关键字
何为可见性?
让一个线程对共享变量的修改,能够及时的被其他线程看到 。
volatile为何能实现线程间的可见?
java内存模型中规定:
- 禁止缓存,对于volatile修饰的变量,不会走CPU高速缓存
- 对于和volatile修饰的变量所有相关的指令都不做指令重排