美文网首页
AtomicInteger源码分析

AtomicInteger源码分析

作者: 发燊 | 来源:发表于2019-06-12 17:07 被阅读0次

    **AtomicInteger** 是Java提供的原子操作类,其内部通过 **UnSafe** 工具类,使用 ==CAS(compare and set)== 的方式保证更新操作的原子性;==*CAS*== 可以看成是一种乐观锁的实现方式,每次更新前会检查当前的值是否符合预期,符合才进行更新;其依赖于底层硬件的指令支持,不同的体系结构的处理器不一样。因为其锁的粒度低,所以在并发下能够提供更优秀的吞吐量表现。

    ---

    下面一起来看下 **AtomicInteger** 的具体实现

    ```java

    public class AtomicInteger extends Number implements java.io.Serializable {

        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();

        private static final long valueOffset;

        static {

            try {

                //jni native

                valueOffset = U.objectFieldOffset

                    (AtomicInteger.class.getDeclaredField("value"));

            } catch (ReflectiveOperationException e) {

                throw new Error(e);

            }

        }

        private volatile int value;

    }

    ```

    在静态代码块中,通过本地方法 *objectFieldOffset()* 获取到 *value* 字段的偏移地址

    ```

    jint find_field_offset(jobject field, int must_be_static, TRAPS) {

      if (field == NULL) {

        THROW_0(vmSymbols::java_lang_NullPointerException());

      }

      oop reflected  = JNIHandles::resolve_non_null(field);

      //获取指定字段的class类型

      oop mirror      = java_lang_reflect_Field::clazz(reflected);

      //转换为JVM中的 Klass 类型

      Klass* k      = java_lang_Class::as_Klass(mirror);

      //获取字段的槽位

      int slot        = java_lang_reflect_Field::slot(reflected);

      //获取字段上的修饰符

      int modifiers  = java_lang_reflect_Field::modifiers(reflected);

      //静态字段

      if (must_be_static >= 0) {

        int really_is_static = ((modifiers & JVM_ACC_STATIC) != 0);

        if (must_be_static != really_is_static) {

          THROW_0(vmSymbols::java_lang_IllegalArgumentException());

        }

      }

      int offset = InstanceKlass::cast(k)->field_offset(slot);

      return field_offset_from_byte_offset(offset);

    }

    ```

    ```

    //instanceKlass.hpp

    FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); }

    //fieldinfo.hpp

    static FieldInfo* from_field_array(Array<u2>* fields, int index) {

        return ((FieldInfo*)fields->adr_at(index * field_slots));

      }

    ```

    其实现方式就是通过JVM内部使用的Klass定位到传入的字段在对象字段表中的偏移量

    ---

    **AtomicInteger** 实现 ==*CAS*== 的方式主要是通过 **UnSafe** 内部的 *compareAndSwapInt()* 方法

    ```

        public final boolean compareAndSet(int expect, int update) {

            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

        }

    ```

    此处传入的valueOffset即在静态代码块中获取到的 *value* 字段相对于具体对象的逻辑偏移量

    ```c++

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

      //获取到要处理的int变量的指针

      jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);

      return (jint)(Atomic::cmpxchg(x, addr, e)) == e;

    UNSAFE_END

    ```

    ```c++

    inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {

      jlong byte_offset = field_offset_to_byte_offset(field_offset);

    #ifdef ASSERT

      if (p != NULL) {

        assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");

        if (byte_offset == (jint)byte_offset) {

          void* ptr_plus_disp = (address)p + byte_offset;

          assert((void*)p->obj_field_addr<oop>((jint)byte_offset) == ptr_plus_disp,

                "raw [ptr+disp] must be consistent with oop::field_base");

        }

        jlong p_size = HeapWordSize * (jlong)(p->size());

        assert(byte_offset < p_size, err_msg("Unsafe access: offset " INT64_FORMAT " > object's size " INT64_FORMAT, byte_offset, p_size));

      }

    #endif

      if (sizeof(char*) == sizeof(jint))    // (this constant folds!)

        return (address)p + (jint) byte_offset;

      else

        return (address)p +        byte_offset;

    }

    inline jlong field_offset_from_byte_offset(jlong byte_offset) {

      return byte_offset;

    }

    ```

    ```

    jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {

      assert(sizeof(jbyte) == 1, "assumption.");

      uintptr_t dest_addr = (uintptr_t)dest;

      uintptr_t offset = dest_addr % sizeof(jint);

      volatile jint* dest_int = (volatile jint*)(dest_addr - offset);

      //获取到当前值

      jint cur = *dest_int;

      //转为byte指针

      jbyte* cur_as_bytes = (jbyte*)(&cur);

      jint new_val = cur;

      jbyte* new_val_as_bytes = (jbyte*)(&new_val);

      new_val_as_bytes[offset] = exchange_value;

      while (cur_as_bytes[offset] == compare_value) {

        jint res = cmpxchg(new_val, dest_int, cur);

        if (res == cur) break;

        cur = res;

        new_val = cur;

        new_val_as_bytes[offset] = exchange_value;

      }

      return cur_as_bytes[offset];

    }

    unsigned Atomic::cmpxchg(unsigned int exchange_value,

                            volatile unsigned int* dest, unsigned int compare_value) {

      assert(sizeof(unsigned int) == sizeof(jint), "more work to do");

      return (unsigned int)Atomic::cmpxchg((jint)exchange_value, (volatile jint*)dest,

                                          (jint)compare_value);

    }

    ```

    atomic_linux_x86.cpp

    ```

    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;

    }

    ```

    可以看到 Java 提供的**UnSafe** 中 ==*CAS*== 操作,在JVM中,主要通过 Atomic.cpp 来实现的,一些具体的操作,又根据不同的处理器体系结构,定义了不同的汇编代码来操作底层硬件指令。

    相关文章

      网友评论

          本文标题:AtomicInteger源码分析

          本文链接:https://www.haomeiwen.com/subject/urzlfctx.html