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操作上锁,并复制了原数组对象,对复制出来的数据进行修改操作,并在最后让原引用指向新对象,如此一来,就解决了并发问题。