在 java 中的 incrementAndGet() 实现中将 getIntVolatile(Object var1, long var2) 替换为 getInt(Object var1, long var2)

replace `getIntVolatile(Object var1, long var2)` with `getInt(Object var1, long var2)` in the implementation of incrementAndGet() in java

根据jdk,AtomicIntegerclass的方法incrementAndGet()的实现如下:

public final int incrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}

如果 getIntVolatile(Object var1, long var2) 方法被 getInt(Object var1, long var2) 方法替换会怎样?

我觉得不用getIntVolatile(Object var1, long var2)方法,因为操作的变量是volatile变量,getInt(Object var1, long var2)可以读到最新的值

看看 incrementAndGet 做了什么:

return unsafe.getAndAddInt(this, valueOffset, 1) + 1;

unsafe 不知道在 valueOffset 处有一个 volatile 字段并且它必须这样对待它。所以,这个(我用的不是var2之类的,而是真正的源码):

v = getIntVolatile(o, offset);

看起来确实可以防止某些可能的 re-orderings。假设您将 getIntVolatile 替换为 getInt:

 do {
      v = getInt(o, offset);
 } while (!weakCompareAndSetInt(o, offset, v, v + delta));

由于这里没有可变语义,编译器可以将读取移出循环:

 int v = getInt(o, offset);
 do {
 } while (!weakCompareAndSetInt(o, offset, v, v + delta));

如果这样做,您可以 end-up 无限循环,非常简单。

getXXX/putXXX Unsafe class 中的普通方法,不考虑 volatile 关键字。他们总是执行一个普通的 load/store,没有内存可见性限制。