【问题标题】:Why does CopyOnWriteArrayList.get need no synchronization?为什么 CopyOnWriteArrayList.get 不需要同步?
【发布时间】:2013-04-10 13:09:34
【问题描述】:

刚刚查看了类 CopyOnWriteArrayList,我想知道为什么它的 get(...) 方法不需要任何同步。 add(...) 和 set(...) 方法使用 ReentrantLock 更改互斥块中的底层数组。但是 get(...) 只是返回原始的底层数组,没有任何同步。好的,底层数组被声明为 volatile:

private volatile transient Object[] array;

但我看不出使用 volatile 如何使任何同步变得多余。它只防止存储在数组中的引用被编译器缓存。如果我明白为什么这里不需要同步,我可以用比以前少一点的锁竞争来编写我的代码......

谢谢,奥利弗

【问题讨论】:

标签: java locking volatile java.util.concurrent


【解决方案1】:

线索就在名字里(正如 MarkRotteveel 指出的那样)。

当进行任何更改时,将在单独的Object[] 中进行更改,然后整个批次将被复制 - “写入时复制”。

当引用从旧的Object[] 更改为新的Object[] 时,内部Object[]volatile,因此所有线程都会接受更改。

【讨论】:

    【解决方案2】:

    它使用了一个小“技巧”​​——当底层数组改变时,事件的顺序是:

    1. 创建一个新数组
    2. 填充新数组
    3. 将类持有的引用更改为指向新数组

    第三步写入private volatile transient Object[] array; - 由于易失语义,在第三步之前所做的所有更改都是可见的。

    所以不仅新的引用可见,而且新数组的内容也可见(这就是诀窍)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-29
      • 2019-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-05
      • 2020-06-05
      • 1970-01-01
      相关资源
      最近更新 更多