CAS AtomicInteger 源码解析

1.CAS简介(复制的,可以跳过看后面代码实例)

CAS,Compare and Swap即比较并替换,设计并发算法时常用到的一种技术,Doug lea大神在java同步器中大量使用了CAS技术,鬼斧神工的实现了多线程执行的安全性。

目前的处理器基本都支持CAS,只不过不同的厂家的实现不一样罢了。CAS有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做并返回false。

public class CAS {

    private static Unsafe unsafe ;

    static{
        loadUnsafe();
    }
    private static void loadUnsafe() {
        try {
            /**Unsafe在rt.jar下,不能直接实例化。必须通过反射*/
            Field field = Unsafe.class.getDeclaredField("theUnsafe") ;
            field.setAccessible(true);
            unsafe = (Unsafe)field.get(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    static class Data{
        int intParam ;
    }
    public static void main(String[] args) throws NoSuchFieldException, SecurityException {

        // objectFieldOffset :  获取  intParam 字段的内存偏移地址
        long intParamOffset = unsafe.objectFieldOffset(Data.class.getDeclaredField("intParam")) ;
        System.out.println(intParamOffset);

        Data data = new Data();
        data.intParam = 2 ;
        /***
         * compareAndSwapInt 比较和 修改值 ,是原子操作
         * 参数1: 要修改的对象
         * 参数2:对象字段的偏移地址
         * 参数3:预期值(如果等于原始值,则修改成功)
         * 参数4:修改后的值
         */
        boolean ret = unsafe.compareAndSwapInt(data, intParamOffset, 2, 13);//原值2, 等于预期值2,能改成功
        if(ret){
            System.out.println("修改intParam成功 , val:"+data.intParam);
        }
        ret = unsafe.compareAndSwapInt(data, intParamOffset, 2, 12);
        if(!ret){
            System.out.println("修改失败");
        }
    }
}

执行结果
12
修改intParam成功 , val:13
修改失败

3.AtomicInteger分析(必须要上面基础)
这里就将了一个getAndSet方法,但是我想就已经足够了。详细解释见 注释。

public class AtomicInteger {
    // jdk自己可以使用, 所以不用我们上面说的反射来获取 Unsafe类实例
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    // AtomicInteger 里 value 值得 内存偏移地址
    private static final long valueOffset;
    // 真正的 int 值
    private volatile int value;

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

    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    public final int get() {
        return value;
    }
    /***
     * 这段代码子在不加锁的情况下通过CAS 实现线程安全,我们设想下方法的执行:
     * 1. 假如 AtomicInteger原始值value为3,既 主存中值为3,根据java内存模型,线程1和线程2各自也拥有一份value的副本,值都是3
     * 
     * 2.线程1运行到 int current = get() 时,获取当前value的值为3 ,此时切换到线程2
     * 
     * 3.线程2开始运行,获取到的值也为3,利用CAS对比内存中的值为3,比较成功,修改了内存 ,此时内存的值变成修改后的4(假如),线程又切换
     * 
     * 4.线程1恢复,利用CAS比较 发现自己的值为3,内存的为4,得出一个结论:此时value正在被另一个线程修改,我不能修改它, CAS操作修改失败
     * 
     * 5.由于value是volatile的 ,所以某个时刻,主内存的值肯定会同步到线程1内的值, 所以代码用循环来执行CAS操作,直到值修改成功
     */
    public final int getAndSet(int newValue) {
        for (;;) {
            int current = get();
            if (compareAndSet(current, newValue))
                return current;
        }
    }
    // CAS 比较操作 ,看上面例子就能懂
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
}

老生常谈:深圳有爱好音乐的会打鼓(吉他,键盘,贝斯等)的程序员和其它职业可以一起交流加入我们乐队一起嗨。我的QQ:657455400

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值