美文网首页
JAVA 源码之线程安全List

JAVA 源码之线程安全List

作者: 东风依旧788 | 来源:发表于2018-02-09 15:54 被阅读0次
    CopyOnWriteArrayList
    • 线程安全版本ArrayList

    • 新增元素

      public boolean add(E e) {
              final ReentrantLock lock = this.lock;
              lock.lock();//进行加锁
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  Object[] newElements = Arrays.copyOf(elements, len + 1);//元素组进行拷贝
                  newElements[len] = e;//将新元素加入到新数组中
                  setArray(newElements);//新数组重新赋值予原数组
                  return true;
              } finally {
                  lock.unlock();//释放锁
              }
          }
      
      • 每新加一个元素都会发生一次全数组拷贝
      • 通过add(index,element)增加元素类似
      • 类似于ArrayList通过addAll进行批量的增加效率要高于单个加入
    • 元素的删除

          public E remove(int index) {
              final ReentrantLock lock = this.lock;
              lock.lock();//加锁
              try {
                  Object[] elements = getArray();
                  int len = elements.length;
                  E oldValue = get(elements, index);
                  int numMoved = len - index - 1;
                  if (numMoved == 0)//当移除最后一个元素时
                      setArray(Arrays.copyOf(elements, len - 1));
                  else {
                      Object[] newElements = new Object[len - 1];
                      System.arraycopy(elements, 0, newElements, 0, index);//分段拷贝
                      System.arraycopy(elements, index + 1, newElements, index,
                                       numMoved);
                      setArray(newElements);//元数据覆盖
                  }
                  return oldValue;
              } finally {
                  lock.unlock();
              }
          }
      
      • 发生一次数组对象拷贝
      • 直接移除元素时,先找到其索引,然后通过以上方法进行移除
      • 同样批量删除的效率高于单个删除
    • 内部类

      • COWIterator
        • next 向后访问
        • previous 向前访问
        • nextIndex 查看下一个索引值
        • previousIndex 前一个索引值
        • 不支持操作:remove,set,add
        • 取值过程不进行mod的检查
      • Spliterators.spliterator
      • COWSubList
    • 特点

      • 变更操作基本是先拷贝出一个副本,操作副本完成后,用副本更新原数据
    SynchronizedList
    • 线程安全List

    • 在get/set/add/remove/indexOf/sort 内部对象进行加锁处理

              public E get(int index) {
                  synchronized (mutex) {return list.get(index);}
              }
      
    • 加锁粒度比较大

    两者对比
    • CopyOnWriteArrayList在数据读上占据优势
    • CopyOnWriteArrayList需要更大的内存空间
    • SynchronizedList使用迭代器需要自己进行线程的同步

    相关文章

      网友评论

          本文标题:JAVA 源码之线程安全List

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