CopyOnWrite容器解决的并发问题
先看这么一段代码: public static void main(String[] args) throws InterruptedException {
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
final ArrayList<String> list = new ArrayList<String>(
a);
Thread t = new Thread(new Runnable() {
int count = -1;
@Override
public void run() {
while (true) {
list.add(count++ + "");
}
}
});
t.setDaemon(true);
t.start();
Thread.currentThread().sleep(3);
for (String s : list) {
System.out.println(s);
}
}
首先一个线程对ArrayList进行遍历操作,此间“休息”一段时间,另外一个线程进来,对List进行加入操作,此时“休息”后的线程继续对list遍历操作,运行爆出以下异常:
这就是ArrayList在并发状态下发生错误,如何解决呢?引出今日猪脚--CopyOnWrite容器。
一、源码
- put方法:
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();
}
}
该方法对put操作上锁,并复制了原数组对象,对复制出来的数据进行修改操作,并在最后让原引用指向新对象,如此一来,就解决了并发问题。