openjdk源碼分析之AtomicLong

關鍵代碼:html

private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset; // 底層value變量的偏移地址
    private volatile long value; //底層變量


static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicLong.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

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

而後看unsafe.cpp中compareAndSwapLong的定義:java

JNINativeMethodide

{CC "compareAndSetLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSetLong)}oop

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
  oop p = JNIHandles::resolve(obj);
  if (p == NULL) {
    volatile jlong* addr = (volatile jlong*)index_oop_from_field_offset_long(p, offset);
    return RawAccess<>::atomic_cmpxchg(x, addr, e) == e;
  } else {
    assert_field_offset_sane(p, offset);
    return HeapAccess<>::atomic_cmpxchg_at(x, p, (ptrdiff_t)offset, e) == e;
  }
} UNSAFE_END
template <DecoratorSet decorators>
template <DecoratorSet ds, typename T>
inline typename EnableIf<
  HasDecorator<ds, MO_SEQ_CST>::value, T>::type
RawAccessBarrier<decorators>::atomic_cmpxchg_internal(T new_value, void* addr, T compare_value) {
  return Atomic::cmpxchg(new_value,
                         reinterpret_cast<volatile T*>(addr),
                         compare_value,
                         memory_order_conservative);
}

template<typename T, typename D, typename U>
inline D Atomic::cmpxchg(T exchange_value,
                         D volatile* dest,
                         U compare_value,
                         atomic_memory_order order) {
  return CmpxchgImpl<T, D, U>()(exchange_value, dest, compare_value, order);
}

// Handle cmpxchg for integral and enum types.
//
// All the involved types must be identical.
template<typename T>
struct Atomic::CmpxchgImpl<
  T, T, T,
  typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type>
{
  T operator()(T exchange_value, T volatile* dest, T compare_value,
               atomic_memory_order order) const {
    // Forward to the platform handler for the size of T.
    return PlatformCmpxchg<sizeof(T)>()(exchange_value,
                                        dest,
                                        compare_value,
                                        order);
  }
};

而後轉到具體平臺相關的實現類,好比mac下的src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hppthis

template<>
template<typename T>
inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
                                                T volatile* dest,
                                                T compare_value,
                                                atomic_memory_order /* order */) const {
  STATIC_ASSERT(8 == sizeof(T));
  __asm__ __volatile__ (  "lock cmpxchgq %1,(%3)"
                        : "=a" (exchange_value)
                        : "r" (exchange_value), "a" (compare_value), "r" (dest)
                        : "cc", "memory");
  return exchange_value;
}

可見mac下采用的是cmpxchgq彙編指令實現:atom

__asm__ 內聯彙編code

lock 鎖消息總線保證互斥地使用這個內存地址orm

AT&T彙編格式: 指令 源操做數 目的操做數htm

cmpxchg : 用RAX中的值與目的操做數的值進行比較,若是相等,則設置ZF標誌並把源操做數加載到目的操做數中,不然清除ZF標誌並把目的操做數加載到RAX中。內存

分析:lock cmpxchgq %1,(%3) 其中%1指exchange_value,%3指dest
首先把compare_value加載到RAX,而後比較RAX與目的操做數(%3即dest)的值,若是相等則把%1即exchange_value的值設置到dest,返回RAX中的值即compare_value。不然把%3即dest中的值加載的RAX寄存器,而後返回RAX中的值。即若是相等返回的是compare_value,不然返回的是dest原來的值。最後那返回的值與比較的值進行比較,相等則返回true表示設置成功。
return HeapAccess<>::atomic_cmpxchg_at(x, p, (ptrdiff_t)offset, e) == e;

相關文章
相關標籤/搜索