Java 线程安全的 List

3,713 阅读1分钟

线程安全的 List

Java 中最常用的 List 为:ArrayListLinkedList,但这两个线程并非是线程安全的,在多线程情况就需要考虑线程安全的 List

Vector

Vector 是在 JDK 1.0 中加入的,历史悠久; 底层原理和 ArrayList 几乎一致,区别在于 Vector 每个公开的方法上都加入了 synchronized 保证并发安全,但性能非常低下,不推荐使用

Collections.synchronizedList()

Collections 集合工具类提供了一个方法可以将 List 转为线程安全的 SynchronizedList

public static <T> List<T> synchronizedList(List<T> list)

原理仅是在每个方法上加上了 synchronized 来保证线程安全,相比于 Vector 扩展性,灵活性更高

public E get(int index) {
    synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
    synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
    synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
    synchronized (mutex) {return list.remove(index);}
}

CopyOnWriteArrayList & CopyOnWriteArraySet

利用写时复制(COW)实现线程安全的集合, 优点是有现成进行修改的时候,仍有其他线程可以读取 缺点是浪费空间,每次添加删除元素就需要复制一份新数组

public boolean add(E e) {
    synchronized (lock) {
 	// 获取底层存储元素的数组
        Object[] es = getArray();
	// 拷贝一份到 es 数组中
        int len = es.length;
        es = Arrays.copyOf(es, len + 1);
	// 把元素添加到末尾
        es[len] = e;
	// 把修改复制回去
        setArray(es);
        return true;
    }
}