原理
public class TestFinal {final int a = 20; //final保证不能读到两个值}
字节码:
写屏障:
之前的指令不会重排序到后面去(有序性)
之前的修改、赋值操作之后会同步到主内存中去(可见性)
0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: bipush 20 // 将值直接放入栈中7: putfield #2 // Field a:I<-- 写屏障10: return
final 变量的赋值通过 putfield 指令来完成,在这条指令之后也会加入写屏障,保证在其它线程读到它的值时不会出现为 0 的情况(初始值)
其他线程访问 final 修饰的变量
-
当数据比较小,复制一份放入(自己的方法栈)栈中直接访问,效率最高
-
大于 short(短整型) 最大值会将其复制到类的常量池,访问时从常量池获取。
第三种:【不加final都算是在堆中,Getstatic速度小于上面两种】