ArrayList、HashSet线程不安全集合

  • Post author:
  • Post category:其他


一、不安全示例

ArrayList是java集合框架中一个重要的类,是一个长度可变的集合。在多线程环境下的操作ArrayList是不安全的,会抛出并发修改异常

ConcurrentModificationException。

话不多说,上示例:

在for循环中new了十个线程,每一个线程都向list中添加元素

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

二、解决方案

1.Vector

List<String> list = new Vector<>();

在jdk1.0时,就发布的Vector集合,该集合中的add方法是加synchornized锁的,可以保障线程安全

public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

虽然synchornized保证了线程安全,但是大大影响了性能

运行结果:

2.Collections

List<String> list = Collections.synchronizedList(new ArrayList<>());

Collections是所有集合的父类,在Collections中有许多加锁的集合,这里将ArrayList改为Collections.synchronizedList(new ArrayList<>()) 使集合变安全

运行结果:


3.CopyOnWriteArrayList

List<String> list = new CopyOnWriteArrayList<>();

CopyOnWriteArrayList是java.util.concurrent为开发者提供的一个线程安全集合,CopyOnWrite就是写入时复制 。

在多线程环境下对一个list进行操作时,读没有影响,但进行写入操作会发生覆盖问题

CopyOnWrite就是在写入的时候避免覆盖,造成数据问题


CopyOnWriteArrayList比Vector的性能要快

Vector底层add方法用的是synchornized,而CopyOnWriteArrayList底层用的是lock锁

public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            //copyOf --- > 写入时复制
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

运行结果:

三、HashSet

HashSet也是线程不安全集合,不过HashSet没有像Vector一样加锁的集合。

使HashSet线程安全的方式:

1.Collections.synchronizedSet

Set<String> set = Collections.synchronizedSet(new HashSet<>());

2.CopyOnWriteArraySet

Set<String> set = new CopyOnWriteArraySet<>();



版权声明:本文为weixin_57504474原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。