跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 为什么 AtomicIntegerArray 的 array 成员不是 volatile 而是 final 的啊?
未分類
12 5 月 2020

为什么 AtomicIntegerArray 的 array 成员不是 volatile 而是 final 的啊?

为什么 AtomicIntegerArray 的 array 成员不是 volatile 而是 final 的啊?

資深大佬 : amiwrong123 5

对比两个原子类:

public class AtomicIntegerArray implements java.io.Serializable {      private final int[] array;          public final int get(int i) {         return getRaw(checkedByteOffset(i));     }      private int getRaw(long offset) {         return unsafe.getIntVolatile(array, offset);     } 
public class AtomicStampedReference<V> {     private static class Pair<T> {         final T reference;         final int stamp;         private Pair(T reference, int stamp) {             this.reference = reference;             this.stamp = stamp;         }         static <T> Pair<T> of(T reference, int stamp) {             return new Pair<T>(reference, stamp);         }     }      private volatile Pair<V> pair;          public V getReference() {         return pair.reference;     }      public int getStamp() {         return pair.stamp;     } 

第一个问题就是:为什么 AtomicIntegerArray 的 array 成员不是 volatile 而是 final 的啊?为啥这么设计啊

第二个问题就是:为什么 AtomicIntegerArray 的 get 函数不能像 AtomicStampedReference 一样实现呢?是因为成员不是 volatile 的呗。直接像下面这样实现,不行吗。如果改成 private volatile int[] array;,是不是就可以了?

    public final int get(int i) {         return array[i];  //类似 pair.reference;     } 

各位大佬,求解答啊

大佬有話說 (7)

  • 資深大佬 : hoholiday

    了解一下 unsafe 类

  • 資深大佬 : luozic

    https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html

  • 主 資深大佬 : amiwrong123

    @hoholiday
    了解了啊。要知道大部分原子类,其数据成员都是 volatile 的,其 get 方法都是直接 return 成员,而不是通过 unsafe 对象 get 。
    但原子数组类,在设计上就不一样了。

  • 資深大佬 : iffi

    AtomicIntegerArray 的 set 方法,通过 putIntVolatile 方式修改(修改的是 array 的某个 index 对应的值,不用对整个 array 加 volatile 修饰)
    public final void set(int i, int newValue) {
    unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
    }

    AtomicStampedReference 的 set 方法,直接=赋值修改,并发情况下,为了内存可见性采用 volatile 修饰
    public void set(V newReference, int newStamp) {
    Pair<V> current = pair;
    if (newReference != current.reference || newStamp != current.stamp)
    this.pair = Pair.of(newReference, newStamp);
    }

  • 主 資深大佬 : amiwrong123

    @iffi
    那如果修改 AtomicIntegerArray 为 private volatile int[] array,再修改 set 函数为 public final void set(int i, int newValue) {array[i] = newValue; } 。

    这样是否可以保证 可见性 呢

  • 資深大佬 : iffi

    @amiwrong123 这个 array 创建好了之后,不会修改其引用指向,所以 private volatile int[] array 不符合语义。修改 set 函数为 public final void set(int i, int newValue) {array[i] = newValue; } 我猜不会保证可见性(你也可以复制 JDK 的源码修改并自己实验验证一下),除非对 array 每一个元素都加 volatile 修饰。这也是为什么要用 unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);

  • 資深大佬 : SoloCompany

    你需要的是 AtomicReference 而不是 AtomicXxxArray

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具