AtomicLongFieldUpdater

AtomicLongFieldUpdater

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;
            }
        }


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

最佳答案

这两个类基本上具有相同的目的,它们都使用内部的Unsafe类来完成“硬性低级”工作。因此,质疑实现差异是合乎逻辑的。

我想在AtomicLongFieldUpdater中完成的回退可能只是一个遗物。在VM_SUPPORTS_LONG_CAS中定义了AtomicLong但仅在AtomicLongFieldUpdater中使用了AtomicLongFieldUpdater这一事实可以证明这一点。

另一个可能性是Java作者决定对性能进行某种程度的优化,但他们只是在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中已经有几乎相同的代码了-请参阅OpenJDK从2007年的“初始加载”提交中的source code。我认为很难在此代码之前进行提交...

09-16 01:13