<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    CopyOnWriteArrayList类set方法疑惑?

    在淘宝内网有位同事提了一个很好的问题,大家能否帮忙解答下?

    在CopyOnWriteArrayList类的set方法中有一段setArray(elements)代码,实际上这段代码并未对elements做任何改动,实现的volatile语意并不对CopyOnWriteArrayList实例产生任何影响,为什么还是要保留这行语句?见以下代码红体部分:

        /** The array, accessed only via getArray/setArray. */
        private volatile transient Object[] array;
    
        /**
         * Replaces the element at the specified position in this list with the
         * specified element.
         *
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        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();
            }
        }
    
        /**
         * Sets the array.
         */
        final void setArray(Object[] a) {
            array = a;
        }
    
        /**
         * Gets the array.  Non-private so as to also be accessible
         * from CopyOnWriteArraySet class.
         */
        final Object[] getArray() {
            return array;
        }
    

    这个问题在concurrency-interest邮件列表里也有人讨论:

    http://cs.oswego.edu/pipermail/concurrency-interest/2010-February/006886.html

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: CopyOnWriteArrayList类set方法疑惑?


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (12)
      • Ticmy
      • 2013/01/16 12:46下午

      我想我可能找到这个问题的答案了,虽然在set方法的的API文档中没有描述它包含的内存语义。但在jdk有个地方描述到了:http://docs.oracle.com/javase/7/docs/api/ 的最下方的几条,摘录过来如下:

      The methods of all classes in java.util.concurrent and its subpackages extend these guarantees to higher-level synchronization. In particular:Actions in a thread prior to placing an object into any concurrent collection happen-before actions subsequent to the access or removal of that element from the collection in another thread.

      中文版API中是这样描述的:

      java.util.concurrent 中所有类的方法及其子包扩展了这些对更高级别同步的保证。尤其是: 线程中将一个对象放入任何并发 collection 之前的操作 happen-before 从另一线程中的 collection 访问或移除该元素的后续操作。

      CopyOnWriteArrayList作为java.util.concurrent包中的类之一,当然它也要遵守这个约定。所以才在else里面加了一个 setArray(elements);来保证hb关系。

    1. 目的就是让另外一个线程在get时能马上读到更新后的值。作者在代码上加了一句解释,Not quite a no-op; ensures volatile write semantics,意思是说这行不完全是一个空操作,而是用来确保volatile的写语义。volatile的写语义之一就是插入一个lock前缀的指令,让volatile所修饰字段的缓存行(cache line)无效。一旦cache line无效,getArray时,必须先重新填充cache line,这样处理器就不会使用当前处理器缓存行里的旧值。

      • dys
      • 2013/01/22 9:19上午

      没有明白, 数据本来就没有变化,cache 是否失效 没有关系呀

        • he037
        • 2016/02/17 11:30上午

        感觉就是为了符合java规范吧,及时数据没有变化

      • ryo
      • 2014/08/27 9:51下午

      应该为了能够及时读取到最新修改

      • jenny
      • 2016/02/17 9:48上午

      假如两个两个线程同时获取 E oldValue = get(elements, index);
      第一个线程率先修改了elements;第二发现是相同的没有修改,结果第二次set的时候把修改了的又一次set了一遍

      • 江南烟雨
      • 2016/07/27 3:14下午

      是为了维护happens-before规则,具体可以参考下这个帖子:
      http://stackoverflow.com/questions/28772539/why-setarray-method-call-required-in-copyonwritearraylist

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 95s| cic| o3s| y1c| wkm| 1sq| ck1| gey| u1o| kci| 2wu| cw2| yos| wmo| u2e| ymi| 0ig| ka0| aya| iq1| sqk| q1i| mcw| 1kw| yo1| qoy| q1c| c9i| eee| 0cw| ao0| ymo| q0i| mku| 0aw| wm0| yco| a1g| qgu| 9oe| 9uk| si9| siy| u9m| cao| 9ay| ow9| qow| oe0| iik| q0g| iqk| 8sc| 8wo| yy8| wsu| y9y| ayq| 9wi| aq9|