zoukankan      html  css  js  c++  java
  • 关于 CopyOnWriteArrayList remove(Object o)方法的疑问记录

    源码如下

     1     /**
     2      * Removes the first occurrence of the specified element from this list,
     3      * if it is present.  If this list does not contain the element, it is
     4      * unchanged.  More formally, removes the element with the lowest index
     5      * {@code i} such that
     6      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
     7      * (if such an element exists).  Returns {@code true} if this list
     8      * contained the specified element (or equivalently, if this list
     9      * changed as a result of the call).
    10      *
    11      * @param o element to be removed from this list, if present
    12      * @return {@code true} if this list contained the specified element
    13      */
    14     public boolean remove(Object o) {
    15         //保存数组快照
    16         Object[] snapshot = getArray();
    17         //获得要查找对象的索引
    18         //这个步骤无锁,是为了减小锁的粒度,提高并发度
    19         int index = indexOf(o, snapshot, 0, snapshot.length);
    20         //根据索引,从数组移除对象
    21         return (index < 0) ? false : remove(o, snapshot, index);
    22     }
    23 
    24     /**
    25      * static version of indexOf, to allow repeated calls without
    26      * needing to re-acquire array each time.
    27      * @param o element to search for
    28      * @param elements the array
    29      * @param index first index to search
    30      * @param fence one past last index to search
    31      * @return index of element, or -1 if absent
    32      */
    33     private static int indexOf(Object o, Object[] elements,
    34                                int index, int fence) {
    35         if (o == null) {
    36             for (int i = index; i < fence; i++)
    37                 if (elements[i] == null)
    38                     return i;
    39         } else {
    40             for (int i = index; i < fence; i++)
    41                 if (o.equals(elements[i]))
    42                     return i;
    43         }
    44         return -1;
    45     }
    46 
    47     /**
    48      * A version of remove(Object) using the strong hint that given
    49      * recent snapshot contains o at the given index.
    50      */
    51     private boolean remove(Object o, Object[] snapshot, int index) {
    52         //进入这个方法有个默认条件,snapshot[index] == o
    53         //而这里要考虑多线程的情况,即原有的数组可能已经被其他线程修改了,snapshot已经是过时的数据
    54         final ReentrantLock lock = this.lock;
    55         lock.lock();
    56         try {
    57             //获取最新数组数据
    58             Object[] current = getArray();
    59             int len = current.length;
    60             if (snapshot != current) findIndex: {
    61                 //考虑数组数据已经被其他线程修改了的情况,要重新定位index值
    62                 int prefix = Math.min(index, len);
    63                 //遍历数组,从0到min(index, len),查找o的index
    64                 for (int i = 0; i < prefix; i++) {
    65                     if (current[i] != snapshot[i] && eq(o, current[i])) {
    66                         index = i;
    67                         break findIndex;
    68                     }
    69                 }
    70                 if (index >= len)
    71                     return false;
    72                 if (current[index] == o)
    73                     break findIndex;
    74                 index = indexOf(o, current, index, len);
    75                 if (index < 0)
    76                     return false;
    77             }
    78             
    79             //实际的删除操作
    80             Object[] newElements = new Object[len - 1];
    81             System.arraycopy(current, 0, newElements, 0, index);
    82             System.arraycopy(current, index + 1,
    83                     newElements, index,
    84                     len - index - 1);
    85             //用新数组替换旧数据
    86             setArray(newElements);
    87             return true;
    88         } finally {
    89             lock.unlock();
    90         }
    91     }

    不明白的地方在于从60行开始,到77行为止,也就是findIndex 这个功能。

    其进入条件是快照数组和当前数组不相等,即其他线程对数组进行了修改的操作,所以需要重新查找index值。在我理解,只需要三行代码就可以解决了,如下:

    index = indexOf(o, current, 0, len);
    if (index < 0)
    return false;

    这个方法是内部实现好的,直接调用饥渴获取到current,即新数组的o对象对应的index值。

    而源码的那种实现我就不太懂了。尤其是循环里面的逻辑:

    if (current[i] != snapshot[i] && eq(o, current[i])) 

    这个判断是处于什么考虑,想破脑袋还是不明白。先记录下来。

    TODO

  • 相关阅读:
    【校招面试 之 C/C++】第1题 为什么优先使用构造函数的初始化列表
    Linux平台ORACLE INSTANT客户端安装
    ORACLE数据库链接
    ORACLE用户管理
    【转】软件开发工具介绍之 6.Web开发工具
    【转】三大UML建模工具Visio、Rational Rose、PowerDesign的区别
    ORACLE数据库查看执行计划
    数据分析方法
    ORACLE对象大小写问题
    计算机改名引发的ORA
  • 原文地址:https://www.cnblogs.com/zhangxuezhi/p/11874334.html
Copyright © 2011-2022 走看看