CopyOnWriteArrayList实现原理

4 篇文章 0 订阅
1 篇文章 0 订阅

引言

《Java并发编程实战》P43中提到:“通过将某个元素放入Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchronizedList或者synchronizedSet中,可以将元素安全的发布到任何从这些容器中访问该元素的线程”。

源码分析

另外,我们知道CopyOnWriteArrayList适用于写少读多的并发场景。那么不妨从源码分析其实现原理。
1.添加时候需要加锁,否则多线程同时写会Copy多个副本。

/**
*Appends the specified element to the end of this list;
@return <tt>true</tt> (as specified by {@link Colelction#add})
*/
public boolean add(T e)
{
    final ReentrantLock lock = this.lock;
    lock.lock();
    try
    {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements,len+1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    }finally{
        lock.unlock();
    }
}

2.读的时候不需要加锁,此时如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的copyOnWriteArrayList。

public T get(int index){
    return get(getArray(),index);
}

总结

虽然CopyOnWriteArrayList保证了写少读多并发线程下元素的安全发布,但是存在两个缺点:
1>内存占用问题。因为CopyOnWrite的写时复制机制,写操作的时候内存会同时驻扎两个对象的问题(复制的时候只是复制容器里的引用,只是在写的时候会创建新对象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)。如果这些内存比较大,可能会造成Yong GC和Full GC。系统如果使用了CopyOnWrite机制更新大对象,容易造成每Full GC,应用响应时间也随之变长。针对内存占用问题,可以通过压缩容器中的元素的方法来减少大对象的内存消耗,比如,如果元素全是10进制的数字,可以考虑把它压缩成36进制或64进制。或者不使用CopyOnWrite容器,而使用其他的并发容器,如ConcurrentHashMap
2> 数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器
注:参考自《Java并发编程实战》、牛客网、blog:http://www.cnblogs.com/dolphin0520/p/3938914.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值