多线程下如何使用List集合
- 使用
Collections.synchronizedArrayList()
,在集合增删改操作上加synchronized锁。默认使用的是当前对象(即创建的synchronized集合),也可以传入要锁的对象。 - 使用
CopyOnWriteArrayList
类进行读写分离:
写时复制,当添加元素时,不直接在原数组上添加,而是先copy数组,复制出一个新容器,然后再新容器中加入元素,添加完元素再将引用指向新容器,这样可以并发的读,而不会读写互斥、提高效率。
但是写时还是要加锁,保证只有一个线程在进行写操作。
为了保证写线程替换数组后对其他读线程立即可见:array数组使用volatile进行修饰。
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock(); // 加锁 保证写操作的并发安全
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock();
}
}