对比两个原子类:
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;
}
各位大佬,求解答啊
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
|