CAS AtomicInteger 源码解析

来源:互联网 发布:qp个案分析比赛知乎 编辑:程序博客网 时间:2024/06/06 07:29

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

原创粉丝点击