
对比两个原子类:
public class AtomicIntegerArray implements java.io.erializable { 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; } 各位大佬,求解答啊
1 hoholiday 2020-05-10 19:10:58 +08:00 via Android 了解一下 unsafe 类 |
2 luozic 2020-05-10 19:40:51 +08:00 |
3 amiwrong123 OP @hoholiday 了解了啊。要知道大部分原子类,其数据成员都是 volatile 的,其 get 方法都是直接 return 成员,而不是通过 unsafe 对象 get 。 但原子数组类,在设计上就不一样了。 |
4 iffi 2020-05-10 20:05:50 +08:00 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); } |
5 amiwrong123 OP @iffi 那如果修改 AtomicIntegerArray 为 private volatile int[] array,再修改 set 函数为 public final void set(int i, int newValue) {array[i] = newValue; } 。 这样是否可以保证 可见性 呢 |
6 iffi 2020-05-10 20:38:02 +08:00 @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); |
7 SoloCompany 2020-05-11 22:36:56 +08:00 你需要的是 AtomicReference 而不是 AtomicXxxArray |