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

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

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

问题

根据 JDK 文档,AtomicInteger 类的 incrementAndGet() 方法的实现如下所示:

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

如果将 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:

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

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 做了什么:

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

unsafe 并不知道在 valueOffset 处有一个 volatile 字段,它必须将其视为这样处理。因此,这段代码(我没有使用 var2 之类的变量,而是真实的源代码):

  1. v = getIntVolatile(o, offset);

肯定看起来是为了防止一些可能的重排序。假设你用 getInt 替换掉 getIntVolatile

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

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

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

如果它这样做了,你可能会陷入一个无限循环,相当简单。

英文:

Look at what incrementAndGet does:

  1. 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):

  1. v = getIntVolatile(o, offset);

surely looks like protects against some possible re-orderings. Let's say you replace that getIntVolatile with getInt:

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

Since there are no volatile semantics here, the compiler can move the read out of the loop:

  1. int v = getInt(o, offset);
  2. do {
  3. } 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:

确定