java多线程(2)之CAS操作

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的修改的线程安全性。

你可能感兴趣的:(java基础相关)