• CopyOnWrite容器


    故障现象

    出现 java.util.ConcurrentModificationException java的并发修改异常。

    ArrayList<String> arrayList = new ArrayList<>();
    for (int i = 0; i < 20; i++) {
                new Thread(() -> {
                    list.add(UUID.randomUUID().toString().substring(0, 8));
                    System.out.println(list);
                }, String.valueOf(i)).start();
    
            }
    
    

    故障分析

    ArrayList没有加锁。
    并发争抢修改导致,查考我们的花名册签名情况。
    一个人正在写入,另外一个同学过来抢夺,导致数据不一致异常。并发修改异常。

    故障解决方案

    3.1 new Vector<>();
    3.2 Collection.synchronizedList(new ArrayList<>);
    3.3 new CopyOnWriteArrayList<>()

    优化建议(同样的错误不犯第二次)

    笔记

    写实复制CopyOnWrite容器即写时复制的容器。往一个容器添加元素的时候,不直接往当前的容器Object[]添加,而是先将当前的容器Object[]进行copy
    复制出一个新的容器Object[] newElements,然后新的容器Object[] newElements里添加元素,添加完,再将原容器的引用指向新的容器setArray(newElements);
    这样做的好处时可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。
    所以CopyOnWrite容器也是一种读写分离的思想,都和写不同的容器
      //出现并发修改异常 ArrayList<String> arrayList = new ArrayList<>();
           // List<String> list = new Vector<String>();
           // List<String> list = Collections.synchronizedList(new ArrayList<>());
            List<String> list =new CopyOnWriteArrayList<>();
    
            for (int i = 0; i < 20; i++) {
                new Thread(() -> {
                    list.add(UUID.randomUUID().toString().substring(0, 8));
                    System.out.println(list);
                }, String.valueOf(i)).start();
    
            }
    
    //其中 CopyOnWriteArrayList的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();
            }

    同样CopyOnWriteArraySet也是线程不安全的。

    而HashSet是否是安全的呢?

    查看源码

    public HashSet() {
    map = new HashMap<>();
    }
    public boolean add(E e) {
    return map.put(e, PRESENT)==null;
    }
    private static final Object PRESENT = new Object();

    其中利用了hashMap的key存储了值,而hashMap的value为一个固定的值new Object()。
  • 相关阅读:
    清北学堂2019.7.18 & 清北学堂2019.7.19
    清北学堂2019.7.17
    清北学堂2019.7.16
    清北学堂2019.7.15
    清北学堂2019.7.14
    清北学堂2019.7.13
    【洛谷P1383 高级打字机】
    考试整理
    考试整理
    【洛谷P5018 对称二叉树】
  • 原文地址:https://www.cnblogs.com/fengyangcai/p/13693415.html
Copyright © 2020-2023  润新知