上回说的arrayList的线程安全问题,juc包中引入了CopyOnWriteArrayList来解决这个问题。
A thread-safe variant of {@link java.util.ArrayList} in which all mutative
operations ({@code add}, {@code set}, and so on) are implemented by
making a fresh copy of the underlying array.
故名思意,解决的思路时写时拷贝。
我们先分析下ArrayList的线程不安全问题:包括的操作只有读/写
1.读读并行并不产生线程安全问题
2.读写并行就有问题了,没法保证读写的执行顺序(期望是写之前读old数据,写完成读new数据)
3.写写并行一样有问题.(期望是写写排队执行)
CopyOnWriteArrayList的解决方案如下:
读读并行不做任何处理;
写写并行通过对写操作进行上锁来解决(使用锁机制ReentrantLock来串行化所有写操作)
读写并行通过对写方式的改造来解决(所有写操作完成,替换整个array内容)
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();
}
因为有锁的限制,保证了写操作的原子性,使得读写操作可以并行
综上所述:读读 读写 写读均可以安全并行,仅仅将写写串行化了,减少了资源竞争的程度。