0
点赞
收藏
分享

微信扫一扫

集合类并发修改异常

前程有光 2021-10-15 阅读 33
技术分享
ArrayList

ArrayList是线程不安全的,add()方法并没有加锁(synchronized),多线程环境下会抛出ConcurrentModificationException。

解决

  • 使用Vector类(使用了synchronized),效率极低。
  • 使用Collections.synchronizedList(new ArrayList<>()),内部直接将接受的List对象传递给静态内部类SynchronizedList对象,然后Collections.synchronizedList(new ArrayList<>())返回的List对象的调用方法都是直接调用输入List对象的方法,但是加了synchronized,类似装饰器模式,也是对输入List的一种增强。
  • 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();
}
}
HashSet

HashSet底层就是一个HashMap,默认的HashSet是一个初始大小为16,负载因子为0.75的HashMap。

解决

  • Collections集合类的static方法SynchronizedSet。
  • CopyOnWriteArraySet,写时复制思想,但是内部还是使用CopyOnWriteArrayList实现。
HashMap

解决

  • Collections集合类的synchronizedMap方法
  • ConcurrentHashMap类
举报

相关推荐

0 条评论