CopyOnWriteArrayList源码分析

1、注解:是 ArrayList   的一个线程安全的变体,其中所有可变操作( add set   等等)都是通过对底层数组进行一次新的复制来实现的。

这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法 有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。“快照”风格的迭代器方法在创建迭代器时使用了对数组状态的引用。此数组在迭代器的生存期内不会更改,因此不可能发生冲突,并且迭代器保证不会抛出 ConcurrentModificationException。创建迭代器以后,迭代器就不会反映列表的添加、移除或者更改。在迭代器上进行的元素更改操作(removeset  add)不受支持。这些方法将抛出 UnsupportedOperationException

2、内存一致性效果:当存在其他并发 collection 时,将对象放入 CopyOnWriteArrayList 之前的线程中的操作 happen-before 随后通过另一线程从CopyOnWriteArrayList 中访问或移除该元素的操作。

3、使用场景:读多,写少,遍历操作不需要进行同步,读写分离。类似一些系统常量的缓存等。

4、源码构造过程:

 privatevolatile transient Object[] array;//定义为volatile引用,可以保证数组引用的可见性


    public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
    Object[] elements = getArray();//volatile的读
    int len = elements.length;
    Object[] newElements = Arrays.copyOf(elements, len + 1);//生成新的数组
    newElements[len] = e;
    setArray(newElements);//volatile的写,保证了对新数组的数据被写入主内存,保证了其他线程读取最新数据
    return true;
} finally {
    lock.unlock();
}
    }

    final Object[] getArray() {
        return array;
    }

    public E get(int index) {
        return (E)(getArray()[index]);//volatile的读,保证了最近写入的对读可见,保证了读取最新的数据
    }

--------------------------------------下面是迭代-------------------------------------

  private final Object[] snapshot;

        private COWIterator(Object[] elements, int initialCursor) {
            cursor = initialCursor;
            snapshot = elements;//对存储数组的引用快照,下面的遍历都是对该变量的操作。该变量是final类型,其他线程写入或者删除元素对该遍历无关。
        }


        public boolean hasNext() {
            return cursor < snapshot.length;
        }


        public boolean hasPrevious() {
            return cursor > 0;
        }


        public E next() {
    if (! hasNext())
                throw new NoSuchElementException();
    return (E) snapshot[cursor++];
        }

你可能感兴趣的:(jvm内存模型,源码,JDK源码分析)