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

huangapple go评论62阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2020年10月15日 23:43:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/64375201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定