java夯实基础:final脑图

final的作用从两个方面理解:基本的锁定功能,帮助JVM实现效率和安全。关于final的解释非常多,本文仅做整理的总结。


基本用法:锁定

final的锁定功能通过final修饰的对象来具体实现,final可以修饰class类/field字段/method方法,被final修饰的不同对象笼统的均处于各自不能再进行修改的状态。此类用法比较简单,知识点梳理请参考下图。


同时,不清楚的内容可以直接参考www.geeksforgeeks.org/final-keywo… 进行深入学习。


高级用法:效率与安全



1) 效率方面方面

final为JIT提供了便利,增加了JIT对代码进行内联的可行性。可参考《java编程思想》中对final提高效率的解释。

2)多线程安全方面

编译器和处理器均会对运行指令进行适当的重排序增进效率,JSR-133针对虚拟机的reordering进行了清晰地规定,其中被final修饰的字段的读load和写store指令的重排序均受到了限制:

(参考:JSR-133, www.infoq.cn/article/jav… )

同时注意,最常见的X86的处理器并不会对loadload和storestore进行重排序。本文重点讲一下final对构造器storestore的重排序的限制。

  • 原理:处理器无法重排序的原因是编译器会在 final 域的写之后,插入一个 StoreStore 屏障,这个屏障禁止处理器把 final 域的写重排序到之后的store语句;
  • 举例说明(参考代码块):假设有两条语句final字段的赋值(x.finalField = v; ) ,其后跟随一条赋值语句将finalField的holding对象赋值给其他线程可见的对象Y (sharedY = x;);这两条语句是不可以重排序的;
  • 常常出现的场景是构造方法时new的过程被重排序,导致字段在没有赋值时被使用;此时final,volatile等阻止重排序的字段均可以保证对象安全;

class MyClass {
  int i;    // 非final语句
  MyClass () {
    i = 1;
  }
}


Thread 1:MyClass clazz = new MyClass();  // clazz是共享变量
Thread 2:  if (clazz != null) {  System.out.println(clazz.i);}


将new分为三步:
1. 分配内存空间给var
2. 初始化var (var.i = 1) 
3. class = var

在没有i final情况下,2和3的顺序可能被重排序,导致thread2在发现clazz非空时,无法获得正确的var.i

复制代码


转载于:https://juejin.im/post/5cea0e77f265da1b8811b8bd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值