我们通常说的Java中的fail-fast机制(快速失败机制),默认指的是Java集合中的一种错误检测机制,当多个线程对集合进行结构性的改变时,有可能会出发fail-fast机制,这个时候会抛出ConcurrentModificationException异常。
为什么ArrayList线程不安全?Vector却线程安全呢?让我们来一探究竟!
ArrayList:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
//ensureCapacityInternal()就是判断如果将当前的新元素加到列表后面,列表的elementData数组的大小是否满足,如果size + 1的这个需求长度大于了elementData这个数组的长度,那么就要对这个数组进行扩容
elementData[size++] = e;
return true;
}
Vector:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
显而易见:在ArrayList中,elementData与size都是全局变量,但没有进行sychronization同步处理,elementData是共享的线程不安全的mutable可变数据。
那么如何解决LIst线程安全问题呢?
- Vector:Vector list = new Vector<>();
- Collections:List list = Collections.synchronizedList(new ArrayList());
- CopyOnWriteArrayList:List list = new CopyOnWriteArrayList<>();
我们来看看 CopyOnWriteArrayList 中的add()方法,原理是使用了 写时复制技术:
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);
// 2、写入新的内容
newElements[len] = e;
// 3、合并
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}



