为了账号安全,请及时绑定邮箱和手机立即绑定

关于CopyOnWriteArrayList源码的疑惑

关于CopyOnWriteArrayList源码的疑惑

九州编程 2019-04-13 08:46:27
jdkconcurrent包当中的CopyOnWriteArrayList定义了一个数组和一个锁:privatevolatiletransientObject[]array;transientfinalReentrantLocklock=newReentrantLock();他的add方法如下:publicbooleanadd(Ee){finalReentrantLocklock=this.lock;lock.lock();try{Object[]elements=getArray();intlen=elements.length;Object[]newElements=Arrays.copyOf(elements,len+1);newElements[len]=e;setArray(newElements);returntrue;}finally{lock.unlock();}}问题:add方法中的finalReentrantLocklock=this.lock;这一句是不是必须的?为什么又定义了一个锁,并且实质用的还是全局定义的那个锁。如果直接用this.lock可不可以?如果不用getArray直接写成intlen=array.length;Object[]newElements=Arrays.copyOf(array,len+1);newElements[len]=o;array=newElements;是不是也可以?
查看完整描述

2 回答

?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

是的。用局部变量lock来引用自身的成员变量当然不是必须的。我认为这是编程演进过程所引入的,很可能和内部执行的规范有关。
例如:内部规范上可能是要求尽量使用accessor来使用成员变量,避免直接使用。即使需要直接使用,最好先用局部变量来引用它。这样做的好处是,这个函数自身具有很好的完备性。设想如果此类如果修改,将lock成员变量取消或者更改类型,如果直接在代码各处引用lock,势必造成很多修改。而在目前的实现上,不过是将finalReentrantLocklock=this.lock;改成finalReentrantLocklock=getLock();影响小得多,语义十分清晰。
同样,对成员变量array的引用也是这样,通过使用accessorgetArray(),代码可以将对成员变量的依赖降低到对一个成员函数的依赖,这对维护也非常有好处。
感谢题主引用了很好的一段程序,提出了一个非常完整的问题。
                            
查看完整回答
反对 回复 2019-04-13
?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

应该还有性能上的考虑.在java函数栈帧的本地变量里存入对域成员对象的引用,相当于一个空间换时间的做法.毕竟取本地变量只需要aload_x一条指令;而取域成员对象的话,需要aload_0[this],getfield两条指令.且每次从栈里取值,应该还有缓存上的好处.
查看完整回答
反对 回复 2019-04-13
  • 2 回答
  • 0 关注
  • 385 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信