【问题标题】:Why do AtomicLong and AtomicLongFieldUpdater implement compareAndSet differently?为什么 AtomicLong 和 AtomicLongFieldUpdater 实现 compareAndSet 的方式不同?
【发布时间】:2019-12-06 08:17:01
【问题描述】:

来自AtomicLong的源码:

    public final boolean compareAndSet(long expect, long update) {
        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
    }

来自AtomicLongFieldUpdater的源码:

    public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
                                                           String fieldName) {
        Class<?> caller = Reflection.getCallerClass();
        if (AtomicLong.VM_SUPPORTS_LONG_CAS)
            return new CASUpdater<U>(tclass, fieldName, caller);
        else
            return new LockedUpdater<U>(tclass, fieldName, caller);
    }

    // CASUpdater extends AtomicLongFieldUpdater
        public final boolean compareAndSet(T obj, long expect, long update) {
            accessCheck(obj);
            return U.compareAndSwapLong(obj, offset, expect, update);
        }

    // LockedUpdater extends AtomicLongFieldUpdater
        public final boolean compareAndSet(T obj, long expect, long update) {
            accessCheck(obj);
            synchronized (this) {
                long v = U.getLong(obj, offset);
                if (v != expect)
                    return false;
                U.putLong(obj, offset, update);
                return true;
            }
        }

我的问题是为什么这两个类使用不同的方式来更新长值? IE。为什么AtomicLongFieldUpdater 有条件地回退到锁定方法,而AtomicLong 没有?

【问题讨论】:

标签: java compare-and-swap


【解决方案1】:

这两个类的目的基本相同,它们都使用内部的Unsafe 类,该类执行“硬低级”工作。因此,质疑实施差异是合乎逻辑的。

AtomicLongFieldUpdater 中完成的后备可能只是一个遗物。这可以得到以下事实的支持:VM_SUPPORTS_LONG_CASAtomicLong 中定义,但仅在AtomicLongFieldUpdater 中使用。

另一种可能性是 Java 作者决定在一定程度上优化性能,但他们只是在 AtomicLongFieldUpdater 中做到了。

答案可能隐藏在VM_SUPPORTS_LONG_CAS的javadoc中:

    /**
     * Records whether the underlying JVM supports lockless
     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
     * method works in either case, some constructions should be
     * handled at Java level to avoid locking user-visible locks.
     */
    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();

恐怕我们必须直接询问作者才能知道确切的推理和含义。 Java 5 中似乎已经有几乎相同的代码了 - 请参阅 2007 年 OpenJDK 的“初始加载”提交中的 source code。我认为在此之前很难提交......

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-19
  • 1970-01-01
相关资源
最近更新 更多