英文:
replace `getIntVolatile(Object var1, long var2)` with `getInt(Object var1, long var2)` in the implementation of incrementAndGet() in java
问题
根据 JDK 文档,AtomicInteger 类的 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) 方法能够读取到最新的值。
英文:
According the jdk ,the implementation of the method incrementAndGet() of AtomicInteger class is as follows:
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;
}
What happens if the getIntVolatile(Object var1, long var2) method is replaced by getInt(Object var1, long var2) method?
What I think is that the getIntVolatile(Object var1, long var2) method is unnecessary, as the operated variable is a volatile variable,the getInt(Object var1, long var2) is able to read the latest value.
答案1
得分: 1
看一下 incrementAndGet 做了什么:
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
unsafe 并不知道在 valueOffset 处有一个 volatile 字段,它必须将其视为这样处理。因此,这段代码(我没有使用 var2 之类的变量,而是真实的源代码):
v = getIntVolatile(o, offset);
肯定看起来是为了防止一些可能的重排序。假设你用 getInt 替换掉 getIntVolatile:
do {
     v = getInt(o, offset);
} while (!weakCompareAndSetInt(o, offset, v, v + delta));
由于这里没有 volatile 语义,编译器可以将读取移到循环外:
int v = getInt(o, offset);
do {
} while (!weakCompareAndSetInt(o, offset, v, v + delta));
如果它这样做了,你可能会陷入一个无限循环,相当简单。
英文:
Look at what incrementAndGet does:
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
unsafe has no idea that at the valueOffset there is a volatile field and it must treat it as such. So, this (I am not using var2 and the like, but the real source code):
v = getIntVolatile(o, offset);
surely looks like protects against some possible re-orderings. Let's say you replace that getIntVolatile with getInt:
 do {
      v = getInt(o, offset);
 } while (!weakCompareAndSetInt(o, offset, v, v + delta));
Since there are no volatile semantics here, the compiler can move the read out of the loop:
 int v = getInt(o, offset);
 do {
 } while (!weakCompareAndSetInt(o, offset, v, v + delta));
If it does that, you can end-up in an infinite loop, pretty trivially.
答案2
得分: 1
Unsafe 类中的普通 getXXX/putXXX 方法并不考虑 volatile 关键字。它们总是执行普通的加载/存储操作,没有内存可见性约束。
英文:
Plain getXXX/putXXX methods in the Unsafe class, do not take the volatile keyword into account. They always perform a plain load/store, without memory visibility constraints.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论