今天JVMPocket天方夜谭群里的一个朋友问了个问题,为什么CyclicBarrier的代码要这样写:
final ReentrantLock lock = this.lock;
lock.lock;
其实如果阅读过java.util.concurrent包下源码的童鞋会发现,不止CyclicBarrier源码是这样做的,这个包下,所有以final修饰的成员变量读取的代码大部分情况都是这样写的,大部分指情况的是:
- 全部的循环代码块里(while、for)读取这些final的成员变量的时候;
- 部分或全部的非循环代码块里读取这些final的成员变量的时候;
为什么要这样做呢?
原因一、为了加快访问速度;
将全局变量赋值给方法的一个局部变量,访问的时候直接在线程栈里面取,比访问成员变量速度要快,读取栈里面的变量只需要一条指令,读取成员变量则需要两条指令;
原因二、为了安全;
如果只是为了访问速度快,那么直接使用一个普通的局部变量即可,不需要加final,加了final原因就是为了多线程下的线程安全。
final的作用,一经初始化就无法被更改,并且保证对象访问的内存重排序,保证对象的可见性,更详细内容见这里
ps: 需要注意的是,当final变量为对象或者数组时:- 虽然我们不能讲这个变量赋值为其他对象或者数组,但是我们可以改变对象的域或者数组中的元素。
- 线程对这个对象变量的域或者数据的元素的改变不具有线程可见性。