首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

快速学习Java中的CopyOnWrite集合

CopyOnWrite集合还是比较简单的,这里做一个简单的介绍。

基础概念

CopyOnWrite翻译过来就是在写的时候才复制,写入时复制是计算机程序设计领域中的一种优化策略。主要思路是如果有多个调用者同时要求相同的资源,他们会共同获取相同的指针指向相同的资源直到某个调用者视图修改资源内容时,系统才会真正复制一份专用副本给该调用者而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的。此做法主要的优点是如果调用者没有修改资源,就不会有副本被创建,因此多个调用者只是读取操作时可以共享同一份资源。

在Java中CopyOnWrite集合只有两个类CopyOnWriteArrayList、CopyOnWriteArraySet,而CopyOnWriteArraySet是基于CopyOnWriteArrayList实现的,所以我们只用看看CopyOnWriteArrayList的实现就能清楚CopyOnWrite的实现了。

CopyOnWriteArrayList基础结构

首先是基础属性,直接看源码,如下图:

可以看到结构还是比较简单的,一个ReentrantLock的锁lock和一个transient与volatile修饰的Object数组array。lock保证线程安全介绍后面的方法会用到,array用来保存数据。

添加方法

添加数据的方法有两类分别为set和add方法,源码如下图:

两个方法流程比较相似,都是先获取到锁,然后复制出一个数组新的数组,set方法的新数组长度不变,add方法新数组长度加1,,set方法是更新新数组的指定位置元素,add方法是把数据添加到新数组的最后,在最后在把新数组设置给array属性。

移除方法

移除方法也分两个,一个是移除指定索引处的元素,一个是移除指定对象的元素,首先是指定索引的方法,源码如下图:

移除指定索引方法还是比较简单的,仍然是先获取到锁,然后判断索引位置,如果是最后一个元素,则只用把旧数组中从0到倒数第二个的元素复制到新的数组中就行了。如果不是最后一个旧数组按索引位置分段复制到新数组就行。

移除指定对象的方法稍微复杂一点,源码如下图:

首先获取到array的快照,再找到对象在数组中的位置,最后才加锁找到对象在最新的array中的位置,根据位置分段进行复制。

总结

这里只分析了更新数据的主要方法,因为查询方法不涉及到加锁和数组的变化整体都比较简单,所以就不去介绍了。

主要是通过分析这几个方法来深入理解CopyOnWrite的思想,通过源码分析发现查询方法都没有加锁,更新方法都加了锁,并且每次更新都是先复制一份,然后在准备好后再更新array,所以新增进去的数据可能不会及时的读到

所以CopyOnWrite容器只能保证数据的最终一致性,但是不能保证数据的实时一致性。不过CopyOnWrite容器比较适用于那些读多写少的场景。

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201012A072YB00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券