基础巩固篇 —— 对不安全集合的理解

一、不安全集合类

说到不安全的集合类,一般会想到ArrayList,HashSet,HashMap,这三种最常用的。

二、ArrayList类的不安全性

不安全原因

ArrayList的底层是数组,new ArrayList()是定义一个空数组{},当添加数据的时候进行扩容,初次扩容容量默认为10,通过Arrays.copyOf(elementData, newCapacity)进行数组复制,实现扩容。为了满足高并发需求,并没有对ArrayList内的方法进行同步实现,这样就会出现多个线程同时进行数组复制操作,然后数据复制异常(ConcurrentModificationException)

解决方案

  1. 使用ArrayList的安全类Vector,Vector中的方法都是被synchronized关键字修饰的,每次调用添加方法只允许一个线程进行操作,保证了线程安全,降低并发量
  2. 使用Collectoins工具类的同步包装方法
List<String> list = Collections.synchronizedList(new ArrayList<>());
  1. 使用java.util.concurrent包下的CopyOnWriteArrayList类
  • 代码:
List<String> list = new CopyOnWriteArrayList<>();
// 添加方法的源码
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();
        }
    }
  • 原理:在进行add方法时添加了ReentrantLock非公平锁,这样就可以保证只能由一个线程进行写操作

二、HashSet类的不安全性

不安全原因

HashSet的底层是HashMap,new HashSet()是new HashMap(),当添加数据的时候,添加的数据作为map的key,value为固定值PRESENT = new Object()。高并发情况下,进行抢占式写入操作时也会造成并发更新数据异常(ConcurrentModificationException)

解决方案

  1. 使用Collectoins工具类的同步包装方法
Set<String> set = Collections.synchronizedSet(new HashSet<>());
  1. 使用java.util.concurrent包下的CopyOnWriteArraySet类
  • 代码:
Set<String> set = new CopyOnWriteArraySet<>();
// 底层调用还是CopyOnWriteArraySet
public CopyOnWriteArraySet() {
        al = new CopyOnWriteArrayList<E>();
    }

三、HashMap类的不安全性

不安全原因

HashMap的底层是数组+链表结构。高并发情况下,进行抢占式写入操作时也会造成并发更新数据异常(ConcurrentModificationException)

解决方案

  1. 使用Collectoins工具类的同步包装方法
Map<String, Object> map = Collections.synchronizedMap(new HashMap<>());
  1. 使用java.util.concurrent包下的ConcurrentHashMap类,它实现了ConcurrentMap接口
  • 代码:
Map<String, Object> map = new ConcurrentHashMap<>();
posted @ 2021-07-20 14:46  不浪小生  阅读(57)  评论(0编辑  收藏  举报