JUC并发编程之集合类线程安全问题

在并发条件下,由于多数集合没有同步控制所以这些集合具有线程不安全性

线程不安全的集合

在这里插入图片描述

线程不安全用例(ArrayList为例)

示例

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

运行会抛出

java.util.ConcurrentModificationException

并发修改异常
出现该异常的原因是,当某个线程正在执行 add()方法时,被某个线程打断,添加到一半被打断,没有被添加完。

解决ArrayList线程不安全问题

  • 可以使用 Vector 来代替 ArrayList,Vector 是线程安全的 ArrayList,但是由于,并发量太小,被淘汰;
  • 使用 Collections.synchronizedArrayList() 来创建 ArrayList;使用 Collections 工具类来创建 ArrayList 的思路是,在 ArrayList 的外边套了一个synchronized外壳,来使 ArrayList 线程安全;
  • 使用 CopyOnWriteArrayList()来保证 ArrayList 线程安全;

CopyOnWriteArrayList

此类采用了写时复制技术,从读写分离的角度去保证了线程的安全性
CopyWriteArrayList之所以线程安全的原因是在源码里面使用 ReentrantLock,所以保证了某个线程在写的时候不会被打断;

/** The array, accessed only via getArray/setArray. */
    private transient volatile Object[] array;

/** The lock protecting all mutators */
    final transient ReentrantLock lock = new ReentrantLock();

  /**
     * Gets the array.  Non-private so as to also be accessible
     * from CopyOnWriteArraySet class.
     */
    final Object[] getArray() {
        return array;
    }

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#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();
        }
    }

可以看到源码开始先是复制了一份数组(因为同一时刻只有一个线程写,其余的线程会读),在复制的数组上边进行写操作,写好以后在返回 true。
这样写的就把读写进行了分离.写好以后因为 array 加了 volatile 关键字,所以该数组是对于其他的线程是可见的,就会读取到最新的值

集合对应线程安全类

ListCopyOnWriteArrayList
SetCopyOnWriteArraySet
MapConcurrentHashMap

ConcurrentHashMap实现线程安全原理与其他不一致
ConcurrentHashMap

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值