• 技术文章 >Java >java教程

    Java原子操作类源码解析

    WBOYWBOY2023-04-21 11:31:07转载21

    我们先来看一下部分源码:

    public class AtomicLong extends Number implements java.io.Serializable {
        private static final long serialVersionUID = 1927816293512124184L;
    
        //1.获取Unsafe类实例
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        //2.存放value的偏移量
        private static final long valueOffset;
        static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
    
        //3.用于判断是否支持Long类型无锁CAS
        private static native boolean VMSupportsCS8();
    
        static {
            try {
                //4.获取value在AtomicLong中的偏移量
                valueOffset = unsafe.objectFieldOffset
                    (AtomicLong.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
        //5.实际变量值
        private volatile long value;
    
        /**
         * Creates a new AtomicLong with the given initial value.
         *
         * @param initialValue the initial value
         */
        public AtomicLong(long initialValue) {
            value = initialValue;
        }
        ············省略部分代码·············
    }

    上面代码中,代码1处通过Unsafe.getUnsafe()获取到Unsafe类的实例(因为AtomicLong类是在rt.jar包下面的,AtomicLong类就是通过Bootstarp类加载器进行加载的)。代码5处,value被声明为volatile类型,保证内存的可见性。通过代码2,4获取value变量在AtomicLong类中的偏移量。

    接下来介绍一下AtomicLong中的主要函数:

    //调用unsafe方法,设置value=value+1后,返回原始的值
    public final long getAndIncrement() {
        return unsafe.getAndAddLong(this, valueOffset, 1L);
    }
    
    //调用unsafe方法,设置value=value-1后,返回原始的值
    public final long getAndDecrement() {
        return unsafe.getAndAddLong(this, valueOffset, -1L);
    }
    
    
    //调用unsafe方法,设置value=value+1后,返回递增后的值
    public final long incrementAndGet() {
        return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
    }
    
    //调用unsafe方法,设置value=value-1后,返回递减后的值
    public final long decrementAndGet() {
        return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
    }

    上面的四个函数内部都是通过调用Unsafe的getAndAddLong方法来实现操作,这个函数是个原子性操作,这里第一个参数是AtomicLong实例的引用的,第二个参数是value变量在AtomicLong的偏移值,第三个参数是要设置的第二个变量的值。

    其中getAndIncrement()方法在JDK7中实现逻辑为:

    public final long getAndIncrement() {
        while(true) {
            long current = get();
            long next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

    如上代码中,每个线程是先拿到变量的当前值(由于value是volatile变量,所以这是获取的最新值),然后在工作内存中对其进行增1操作,而后使用CAS修改变量的值,如果设置失败,则循环继续尝试,直到设置成功。

    JDK8中的逻辑为:

    public final long getAndIncrement() {
            retrturn unsafe.getAndAddLong(this, valueOffset, 1L);
        }

    其中JDK8中的unsafe.getAndAddLong的代码为:

    public final long getAndAddLong(Object var1, long var2, long var4) {
       long var6;
       do {
           var6 = this.getLongVolatile(var1, var2);
       } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));
    
       return var6;
    }

    从中可以看到,JDK7中的AtomicLong中循环逻辑已经被JDK8中的原子操作类Unsafe内置了。

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

    函数在内部调用了unsafe.compareAndSwapLong方法。如果原子变量中的value值等于expect,则使用update值更新该值并返回true,否则返回false。

    以上就是Java原子操作类源码解析的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:亿速云,如有侵犯,请联系admin@php.cn删除
    专题推荐:Java
    上一篇:Java中如何定义数据类型 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 如何利用JAVA中的继承、构造方法以及重写和重载方法?• 如何使用Java实现考试奖励?• 使用@Valid,@Validated和@PathVariable的Java代码示例及使用方法• Java位运算示例代码分析• Java内部类示例分析
    1/1

    PHP中文网