vector、synchronizedList、CopyOnWriteArrayList 三者的区别

参考 https://blog.csdn.net/dimu9293/article/details/107729756

三者底层原理

1、vector是通过在每个方法加synchronized实现,包括最简单的size()方法

public synchronized int size() {
    return elementCount;
}
    public synchronized boolean isEmpty() {
    return elementCount == 0;
}

2、synchronizedList是通过在每个方法内部加 synchronized实现,包括最简单的size()方法

        public int size() {
            synchronized (mutex) {return m.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized (mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized (mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
        }

3、CopyOnWriteArraylist是通过复制一份副本,然后通过修改副本之后再赋值回去,lock是new()出来的,用于在set,add等写操作的时候进行锁操作

final transient Object lock = new Object();

public E set(int index, E element) {
        synchronized (lock) {      
            Object[] es = getArray();
            E oldValue = elementAt(es, index);

            if (oldValue != element) {
                es = es.clone();
                es[index] = element;
                setArray(es);
            }
            return oldValue;
        }
    }


//获取迭代器的时候是复制了一个新的数组
public Iterator<E> iterator() {
        return new COWIterator<E>(getArray(), 0);
}

三者的优缺点

类型 缺点 优点
vector 所有操作都要加锁,性能不佳 即使在高并发环境下都能保证数据的一致性
synchronizedList 同上 同上
CopyOnWriteArrayList 写操作会有一定的延迟 只有写加锁,读不加锁

解析:
1、由于vector与synchronizedList都是通过加synchronized实现,两者性能上差距并不大。但是由于每次调用方法都要加锁,导致在大数据量的情况下性能不理想。
2、CopyOnWriteArrayList 由于写锁读不锁使得性能更好,但是由于写操作是在副本上进行的,在数据量大的情况下数组的复制比较耗时,所以写完后不能立马体现出来,有一定的延迟。

CopyOnWriteArrayList 读写不一致的场景示例

1.循环中删除元素不报错

例子
List<String> list = new CopyOnWriteArrayList();    //CopyOnWriteArrayList换成ArrayList则直接报错
        list.add("A1");
        list.add("A2");
        list.add("A3");
        for (String str : list) {
            if ("A1".equals(str)) {
                list.remove(str);
            }
        }
System.out.println(list);

//运行结果        
[A2, A3]

2.迭代过程中往list添加或减少元素不会立马体现

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList();
list.add("A1");
list.add("A2");
list.add("A3");

Iterator<String> it = list.iterator();
list.add("A4");
while (it.hasNext()){
    System.out.println(it.next());
}

//运行结果
A1
A2
A3

3.不支持remove操作
为了保证数据不错乱,CopyOnWriteArrayList不支持在迭代器中进行remove操作。
在CopyOnWriteArrayList中

public Iterator<E> iterator() {
    return new COWIterator<E>(getArray(), 0);
}

在 COWIterator 中

public void remove() {
    throw new UnsupportedOperationException();
}

测试

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList();
list.add("A1");
list.add("A2");
list.add("A3");

Iterator<String> it = list.iterator();
list.add("A4");
while (it.hasNext()){
    it.remove();
    System.out.println(it.next());
}

结果:
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.base/java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1120)
	at STU_CopyOnWriteArraylist.read(STU_CopyOnWriteArraylist.java:20)
	at STU_CopyOnWriteArraylist.main(STU_CopyOnWriteArraylist.java:7)
posted @   NeverLateThanBetter  阅读(134)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示