【Java锁体系】CopyOnWriteArrayList是什么?线程安全的arraylist是哪个?
发布日期:2021-06-29 15:36:13 浏览次数:3 分类:技术文章

本文共 2031 字,大约阅读时间需要 6 分钟。

【Java锁体系】-CopyOnWriteArrayList

一、背景

说到CopyOnWriteArrayList就需要说下,ArrayList。ArrayList是非线程安全的,也就是说在多个线程下进行读写,会出现异常。

那么ArrayList既然是非线程安全的,那么我们使用一些机制把它变为安全的就可以了。比如说替换成Vector,再或者是Collections,可以将ArrayList包装成一个线程安全的类。

不过Vector和collections的包装,有一个很大的缺点,就是它们使用的都是独占锁,独占锁在同一时刻只能有一个线程获取,效率太低。于是CopyOnWriteArrayList出现了。

二、CopyOnWriteArrayList介绍

(1)独占锁效率低:采用读写分离思想解决

读操作不加锁,所有线程都不会阻塞。写操作加锁,线程会被阻塞;

(2)写线程获取到锁,其它线程包括读线程阻塞

但是这时候又出现了另外一个问题:写线程获取到锁之后,其它的读线程会陷入阻塞

(3)复制思想

当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行copy,复制出一个新的容器,然后往新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。

但这时候会抛出一个新的问题,也就是数据不一致的问题。如果写线程还没来得及写回内存,其他线程就会读到脏数据。这是copyonwritelock的缺点。

其适用场景就是读多写少的情况下比较好。

三、CopyOnWriteArrayList的实现

1.get方法

/**     * {@inheritDoc}     *     * @throws IndexOutOfBoundsException {@inheritDoc}     */	// get这个方法很简单,没有加锁,主要通过getarray来实现的。    public E get(int index) {
return get(getArray(), index); }/** * Gets the array. Non-private so as to also be accessible * from CopyOnWriteArraySet class. */ final Object[] getArray() {
return array; }

整个读的过程没有添加任何锁,就是普通的数组获取。

2.add方法

/**     * Appends the specified element to the end of this list.     *     * @param e element to be appended to this list     * @return {@code true} (as specified by {@link Collection#add})     */    public boolean add(E 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(); } }

写操作添加了一个锁ReentrantLock,这个锁可以决定在什么时候加锁和释放更加灵活。保证了写操作线程安全。能够体现copy的思想是Arrays.copyOf(elements,len+1),也就是数组复制了一份,最后setArray回去了。

四、CopyOnWriteArrayList和ConcurrentReadWriteLock总结

读写锁ConcurrentReadWriteLock

读线程具有实时性,写线程会阻塞,解决了数据不一致的问题。但是读写锁依然会出现读线程阻塞等待的情况。

CopyOnWriteArrayList

读线程具有实时性,写线程会阻塞。不能解决数据不一致的问题。但是CopyOnWriteArrayList不会出现读线程阻塞等待的情况。

转载地址:https://codingchaozhang.blog.csdn.net/article/details/115433611 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【SQL面试题】Leetcode中SQL题目练习
下一篇:【Java锁体系】ReadWriteLock读写锁是什么?什么是读写锁

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月09日 19时38分21秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章