集合类-线程安全问题

集合类不安全的问题

List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    new Thread(()->{
        //多个线程修改同一个资源list
        list.add(UUID.randomUUID().toString());
        System.out.println(list);
    }).start();
}

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

解决方案

  1. Vector 线程安全的, 加了重锁(不推荐)
  2. List list = Collections.synchronizedList(new ArrayList<>()); // Collections工具类
  3. CopyOnWriteArrayList list = new CopyOnWriteArrayList(); // JUC (推荐)

CopyOnWriteArrayList为什么能解决线程安全问题

//array用volatile修饰保证可见性
private transient volatile Object[] array;

public boolean add(E e) {
    // 加锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        //复制到一个新的数组,数组长度加1 
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        //设置新的数组为当前集合
        setArray(newElements);
        return true;
    } finally {
        //释放锁
        lock.unlock();
    }
}

HashSet 线程不安全问题

  1. Set set = Collections.synchronizedSet(new HashSet<>());
  2. CopyOnWriteArraySet set = new CopyOnWriteArraySet();
//内部构造的还是CopyOnWriteArrayList
public CopyOnWriteArraySet() {
    al = new CopyOnWriteArrayList<E>();
}

HashSet 底层数据结构就是HashMap

public HashSet() {
    map = new HashMap<>();
}

//key是值,value是Object对象常量
private static final Object PRESENT = new Object();
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

HashMap 线程安全问题 解决方案

Map<String, String> map = new ConcurrentHashMap();
posted @ 2021-09-30 10:09  紫川先生  阅读(29)  评论(0编辑  收藏  举报