zoukankan      html  css  js  c++  java
  • AQS源码解析(一)-AtomicBoolean源码解析

    • 基本类:
    • 数组类型:
      • AtomicIntegerArray
      • AtomicLongArray
      • AtomicReferenceArray

    介绍

    由于在多线程条件下,如果对共享变量修改容易造成数据不一致的情况,所以对于共享变量需要保证线程安全有有如下几种方式:

    1. 使用lock或者synchronized进行同步共享变量
    2. 使用CAS方法来保证修改变量为原子性操作

    该类为后者,基于CAS方式修改具有原子性。

    实现原理

    1. 将boolean中的true转换成int类型表示:1表示true 0表示false
    2. 在类进行初始化的时候获取该值的内存地址
    3. 调用Unsafe.compareAndSwant方法底层通过CAS原理(CPU中cmpxchg指令)对值进行变化

    特点

    1. 基于CAS实现线程安全
    2. 实现了Cloneable接口,能被克隆
    3. 实现了Serializable接口,支持序列化传输

    源码解析

    成员变量

        private static final long serialVersionUID = 4654671469794556979L;
        // setup to use Unsafe.compareAndSwapInt for updates
        //使用unsafe类进行cas
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        //获取该值得偏移量(内存中的地址)
        private static final long valueOffset;
        /**
         * 内部使用int来做boolean的设置
         * 默认为0
         */
        private  volatile int value;
    
    1. serialVersionUID:序列化ID
    2. unsafe:该类是Atomic中核心类,用于执行低级别,对内存进行操作,内部都是native方法
    3. valueOffset:字段value的内存偏移地址
    4. value:真实value,1表示true 0表示false,使用volatile保证内存可见性

    类初始化过程

        static {
            try {
               //返回对象成员属性在内存地址相对于此对象的内存地址的偏移量
                valueOffset = unsafe.objectFieldOffset
                    (AtomicBoolean.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
    

    主要是通过unsafe方法获取value值得内存偏移地址

    成员方法

    get()

    获取该boolean变量

        /**
         * 返回当前值
         */
        public final boolean get() {
            return value != 0;
        }
    

    boolean compareAndSet(boolean expect, boolean update)

    比较前值后赋值,可能存在赋值失败的情况

         /*
          * 只有当期待的值为expect的时候才会更新相关值
          *  1. 期待的值等于现在值,则成功赋值,返回true
          *  2. 期待的值不等于现在的值,则赋值失败,则返回false
          */
        public final boolean compareAndSet(boolean expect, boolean update) {
            int e = expect ? 1 : 0;
            int u = update ? 1 : 0;
            return unsafe.compareAndSwapInt(this, valueOffset, e, u);
        }
    
    1. 将boolean转换成int类型
    2. 调用compareAndSwapInt进行CAS赋值
    3. 返回true则表示成功,false表示失败

    boolean getAndSet(boolean newValue)

    比较前值后进行赋值,用的相对较多

        public final boolean getAndSet(boolean newValue) {
            boolean prev;
            do {
                prev = get();
            } while (!compareAndSet(prev, newValue));
            return prev;
        }
    
    
    1. 先获取之前值
    2. 在调用循环compareAndSet进行CAS赋值

    void set(boolean newValue)

    无条件设置值,用的相对较少

        public final void set(boolean newValue) {
            value = newValue ? 1 : 0;
        }
    
    

    void lazySet(boolean newValue)

    也是赋值操作,该操作会让Java插入StoreStore内存屏障,避免发生写操作重排序

    public final void lazySet(boolean newValue) {
        int v = newValue ? 1 : 0;
        unsafe.putOrderedInt(this, valueOffset, v);
    }
    

    总结

    1. 该类是原子性boolean类,是线程安全的
    2. 该原子类的核心操作都是基于Unsafe类
    3. CAS普遍会产ABA问题
  • 相关阅读:
    spring mvc ajax请求
    spring mvc 返回页面数据
    spring mvc 参数传递的三种方式
    spring mvc 注解示例
    spring mvc handler的三种方式
    MyBatis 一级、二级缓存
    MyBatis 调用存储过程
    MyBatis动态SQL与模糊查询
    spring mvc 注解入门示例
    MyBatis 一对多关联查询
  • 原文地址:https://www.cnblogs.com/lonecloud/p/11392032.html
Copyright © 2011-2022 走看看