美文网首页
ArrayList、CopyOnWriteArrayList读写

ArrayList、CopyOnWriteArrayList读写

作者: 云海_54d4 | 来源:发表于2018-05-22 14:11 被阅读0次

    1.关于ConcurrentModificationException和迭代器读写(ArrayList)
    a) foreach语法底层其实是使用了iterator。
    b) ArrayList在remove/add时会修改一个变量modCount。
    c) ArrayList的迭代器是其一个内部类,在创建这个迭代器对象时,它保留了当时的modCount的值,在调用迭代器方法时,会先检测ArrayList.modCount和快照是否相同如果不相同则抛出ConcurrentModificationException。
    d) ArrayList的set方法不会修改modCount,所以在迭代器迭代时可以调用set
    e) ArrayList的迭代器的remove/add方法内部是调用ArrayList的remove/add,同时更新了自己的modCount快照,所以迭代器修改会造成其他迭代器的ConcurrentModificationException
    f)所以for(int i = 0; i < size; i++)不会造成ConcurrentModificationException


    2.关于锁和读写(CopyOnWriteArrayList)
    a) 所有读的方法和ArrayList没区别,都是直接从源数组里直接随机读取
    b) 所有修改的方法add/remove/set/clear共享一把lock
    c) add/remove/set都是基于Arrays.copyOf(),产生一个新数组,再将源数组array指向新的数组对象
    e) 没有modCount
    d) 为什么加写锁了还要复制 -> 为什么写锁要和读锁互斥 -> 64位long型对于32位JVM要写两次,是不保证原子性的,这就可能读到只写了一半的long型(虽然现在虚拟机都实现的long/double的原子性操作,但是jvm规范并没有要求)
    f) 所以可以认为CopyOnWriteArrayList是用写时复制代替了读锁,把读的复杂度移到了写时,所以适合读多写少的业务
    d) addIfAbsent() 如果没有则添加,CopyOnWriteArraySet内部其实是CopyOnWriteArrayList,add方法调用了CopyOnWriteArrayList#addIfAbsent


    3.关于迭代器和UnsupportedOperationException(CopyOnWriteArrayList)
    a) CopyOnWriteArrayList的迭代器是其一个内部类,在创建这个迭代器对象时,他保留了当时的源数组,迭代是基于当时快照的,所以对CopyOnWriteArrayList的迭代可能是旧的数据
    b) 迭代器代表的是一个过时的数组,所以对过时数组的修改是没有意义的,所以迭代器的修改方法直接抛出UnsupportedOperationException
    c) 因为没有modCount所以foreach迭代时可以随便修改list,但是要忍受迭代的过期数据


    4.关于subList
    a) 对subList的读写其实都是委托源List,所以subList可以看成对index的附加约束
    b) CopyOnWriteArrayList的subList是其一个内部类,在创建subList对象时,保留了源list当时的内部array的引用,在之后调用subList的方法时,会校验list的array是否改变如果改变则抛出CopyOnWriteArrayList,而通过subList修改源list后,subList会更新保留的array引用,类似ArrayList的迭代器修改
    c) ArrayList的subList是其一个内部类,行为都相似,不过他是通过modCount来做同步校验的,和ArrayList.Iterator基本相同


    5.关于扩容
    a) CopyOnWriteArrayList在修改时产生新的、大小正好的数组,所以没有扩容问题
    b) ArrayList当array剩余空间不足时进行扩容,扩容后的容量是原来的1.5倍,不超过Integer.MAX_VALUE,没有loadfactor这一说


    6.关于System.arraycopy和Arrays.copyOf
    a) 关于数组的操作上是靠这两个
    System.arraycopy(fromArr, fromIndex, toArr, beginIndex, len)
    add(int index, Object element):
    System.arraycopy(elementData, index, elementData, index + 1, size - index)
    elementData[index] = element
    remove(int index):
    System.arraycopy(elementData, index+1, elementData, index, size - index - 1)
    elementData[--size] = null
    b)Arrays.copyOf()其实内部是new了一个新的数组,并调用System.arraycopy()把数据写入新数组再返回

    相关文章

      网友评论

          本文标题:ArrayList、CopyOnWriteArrayList读写

          本文链接:https://www.haomeiwen.com/subject/dfmhjftx.html