gpt4 book ai didi

java - 为什么 AtomicReference CAS 返回值为 128 的 false?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:58:49 25 4
gpt4 key购买 nike

我使用 AtomicReference 来实现 AtomicInteger。然而,在测试中,我注意到即使在单线程环境中,一旦 CAS 操作的值达到 128,CAS 操作就会卡住。我是做错了什么还是 AtomicReference 中有警告(可能与 CPU 相关)?这是我的代码:

public class MyAtomInt {
private final AtomicReference<Integer> ref;

public MyAtomInt(int init) {
ref = new AtomicReference<Integer>(init);
}

public MyAtomInt() {
this(0);
}

public void inc() {
while (true) {
int oldVal = ref.get();
int nextVal = oldVal + 1;
boolean success = ref.compareAndSet(oldVal, nextVal); // false once oldVal = 128
if (success) {
return;
}
}
}

public int get() {
return ref.get();
}

static class Task implements Runnable {

private final MyAtomInt myAtomInt;
private final int incCount;

public Task(MyAtomInt myAtomInt, int cnt) {
this.myAtomInt = myAtomInt;
this.incCount = cnt;
}

@Override
public void run() {
for (int i = 0; i < incCount; ++i) {
myAtomInt.inc();
}
}
}

public static void main(String[] args) throws Exception {
MyAtomInt myAtomInt = new MyAtomInt();
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.submit(new Task(new MyAtomInt(), 150)).get();
System.out.println(myAtomInt.get());
exec.shutdown();
}
}

最佳答案

这样做的原因是,当您将 int 装箱到 Integer 中时,您可能会也可能不会创建一个新的 Integer 实例。如果这样做,那么新实例可能与其他 Integer 实例不具有引用相等性,即使它们共享相同的值。 AtomicReference.compareAndSet() 使用引用相等(身份)进行比较。

关键在于编译器如何处理 int 值的自动装箱:它发出对 Integer.valueOf() 的调用。作为一种优化,Integer.valueOf() 有一个装箱整数的缓存,默认情况下该缓存包含最大 128 的值。如果您将一个整数 n 装箱两次,您如果值足够小可以在缓存中,每次都会得到相同的 Integer 引用;否则,您将获得两个单独的实例。

目前,您对旧值进行拆箱,计算新值,当您调用 compareAndSet() 时,您再次对旧值进行装箱。达到 128 后,您将停止获取缓存值,因此第二个盒装副本不再是 AtomicReference 中的副本。

关于java - 为什么 AtomicReference CAS 返回值为 128 的 false?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24209702/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com