..

Juc 1

本章主要介绍JUC包当中的一些并发处理

cas

    /**
     * Atomically update Java variable to <tt>x</tt> if it is currently
     * holding <tt>expected</tt>.
     * @return <tt>true</tt> if successful
     */
    public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);

上面的代码大家可能都比较熟悉,是Unsafe下的对于int属性的cas操作。native方法我们直接去JNI查找实现

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");
  oop p = JNIHandles::resolve(obj);
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

上面的代码主要分为3步骤

  1. 根据对象获取oop描述信息
  2. 根据偏移量获取绝对地址
  3. 执行cas原子操作

本文只对步骤3进行讨论

我们能看到很多处理器下的实现 在此我们只聚焦于X86

#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "


inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  int mp = os::is_MP();
  __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
                    : "=a" (exchange_value)
                    : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
                    : "cc", "memory");
  return exchange_value;
}

以上代码是先判断当前机器是否为多核处理器并存储在mp变量当中。然后作为入参执行内联汇编。 LOCK_IF_MP判断如果是多处理器则插入 LOCK 指令。然后执行 cmpxchgl 进行比较并交换。