java多线程(2)之CAS操作

来源:互联网 发布:ubuntu设置中文输入法 编辑:程序博客网 时间:2024/05/16 04:53

CAS:Compare and Swap即比较交换技术,它在高并发开发中是很重要的技术,在了解什么是CAS操作之前我们首先需要简单了解下sun.misc.UnSafe类。


UnSafe类中的很多方法都是Native方法,没法直接调用,只能通过JNI操作调用本地方法,这里列举个里面的本地方法:

public native long objectFieldOffset(Field var1);获取对象中给定的var1字段在内存地址中的偏移量。

这里可以了解到UnSafe提供硬件级别的操作,比如获取对象在内存中的地址,修改内存中的值等,它在并发中是很常用的。

简单介绍了UnSafe类后,接下来介绍CAS操作。


CAS

CAS是通过UnSafe实现的,UnSafe中包含如下三个本地方法提供支持

public final native boolean compareAndSwapObject(Object var1, long  var2, Object var4, Object var5);public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论V值是否等于A值,都将返回V的原值。CAS 有效地说明了:我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。

eg.
原子操作类AtomicInteger采用的就是CAS设计来保证多线程安全的,接下来就拿该类做下分析。

public class AtomicInteger extends Number implements java.io.Serializable {    private static final long serialVersionUID = 6214790243416807050L;    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();    private static final long VALUE;    static {        try {            VALUE = U.objectFieldOffset// 这里的值是内存中"value"字段的内存地址偏移量                (AtomicInteger.class.getDeclaredField("value"));        } catch (ReflectiveOperationException e) {            throw new Error(e);        }    }    private volatile int value;...此处省略  /**     * Atomically increments by one the current value.     *     * @return the updated value     */    public final int incrementAndGet() {        return U.getAndAddInt(this, VALUE, 1) + 1;    }
U.getAndAddInt中对应的方法为UnSafe类中的public final int getAndAddInt(Object var1, long var2, int var4) {        int var5;        do {            var5 = this.getIntVolatile(var1, var2);获取对象中的Volatile类型的VALUE对应内存中存储的值        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//在多个线程访问时避免出现读取的值与内存中的值不一致,这时会循环执行比较直到二者相等,然后修改内存中的值为var5+var4(这里var4是1),然后返回true        return var5;//返回内存中修改之前的值,所以后面会调用U.getAndAddInt(this, VALUE, 1) + 1    }    public native int getIntVolatile(Object var1, long var2);    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);//调用native方法执行CAS操作

整个过程中,利用CAS机制保证了对于value的修改的线程安全性。

原创粉丝点击