目录
一、学习总结
- 1、指令重排(编译器、处理器重排)
目的就是把CPU的资源利用起来,这样就能就能提升整个计计算机的效率,性能优化。
重排的原则:在不改变单线程语义情况下(即不改变单线程执行程序的结果,也就是程序结果不会改变),允许对程序执行顺序重排。 即遵循as-if-serial。
同一个方法中,没有语句依赖关系的程序,执行顺序可能会被重排
a=1; //1
b=2; //2
c=a+1; //3
因位b=2;没有上下文依赖,因此编译器优化后可能执行顺序如下:
b=2; //2
a=1; //1
c=a+1; //3
- 2、重排序对多线程的影响
例如两个线程分别调用下面的两个方法,调用getValue()方法的线程,输出的value可能为0。因位在init方法中,可能会先执行flag=true; ,然后再执行,value=8;
private static int value;
private static boolean flag;
public static void init(){
value=8; //语句1
flag=true; //语句2
}
public static void getValue(){
if(flag){
System.out.println(value);
}
}
- 3、禁止重排序
编译器无法根据语义来知道代码指令的依赖关系,因此需要人显示的告诉编译器,某个地方禁止指令重排。
在cpu和编译器层面都提供了一套内存屏障,来禁止重排指令。JAVA内存模型JMM把这些负责的给封装后简单化了。
程序员可以通过Volatile、synchronized、final几个关键字告诉编译器和处理器哪些地方是不允许进行重排序的。
- 4、总结:
[1]为什么要进行指令重排(提高cpu利用率、提高性能)
[2]三种指令重排的场景(编译器、指令集并行的重排、内存重排)
[3]指令重排原则(as-if-serial)
[4]单线程重排、多线程重排、禁止重排