在 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,没有内存可见性限制。
根据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,没有内存可见性限制。