CAS理解

本文基本节选自
Java theory and practice: Going atomic

CAS字面上是什么意思?

CAS = Compare-and-Swap. 它的语义是:

public class SimulatedCAS {
     private int value;

     //如果某个值当前值是期望值,则将某个值设置为新值;否则不做设置.
     //然后,返回当前值
     public synchronized int compareAndSwap(int expectedValue, int newValue) {
         int currentValue = value;
         if (value == expectedValue)
             value = newValue;
         return currentValue;
     }
}

CAS在并发控制上起什么作用?

以“自增操作”为例,使用CAS可以避免常见的“丢失修改”问题

    private SimulatedCAS value;
    public int increment() {
        int oldValue = value.getValue(); //CAS操作之前先拿一下当前值
        while (value.compareAndSwap(oldValue , oldValue + 1) != oldValue ){ //如果CAS的返回值不等于CAS操作之前的值,那说明在CAS操作之前value已经被其他线程修改,那么本线程的修改就会造成“丢失修改”,所以这里要放弃修改;而应该重取一次当前值,并再来一次CAS,直到CAS操作成功
            oldValue = value.getValue(); 
        }
        return oldValue + 1;  //如果CAS操作成功,说明value在取当前值之后没被其他线程修改,所以这里可以返回 原值 + 1
    }

另外你可能注意到,要保证compareAndSwap()操作的语义正确性,这个方法本身必须是原子操作。

要避免“丢失修改”问题,用synchronized关键字也能保证,为什么要用CAS? 因为CAS避免了锁,性能会比较好。

那上面的compareAndSwap()是原子方法,不也得用synchronized关键字、用锁了吗? 事实上的Java CAS操作是不需要用syncrhonzied关键字的,因为它根本不是通过java代码实现,而是依赖CPU或操作系统本地代码实现的,一般来说CPU直接支持CAS原语,从硬件上保障了CAS操作的原子性。

JRE中现成的CAS操作

可以观察一下如何用AtomicInteger这个带CAS功能的类来实现伪随机数。可以体会一下下面的代码,就不细说了。


public class PseudoRandomUsingSynch implements PseudoRandom {
    private int seed;

    public PseudoRandomUsingSynch(int s) { seed = s; }

    public synchronized int nextInt(int n) {
        int s = seed;
        seed = Util.calculateNext(seed);
        return s % n;
    }
}

public class PseudoRandomUsingAtomic implements PseudoRandom {
    private final AtomicInteger seed;

    public PseudoRandomUsingAtomic(int s) {
        seed = new AtomicInteger(s);
    }

    public int nextInt(int n) {
        for (;;) {
            int s = seed.get();
            int nexts = Util.calculateNext(s);
            if (seed.compareAndSet(s, nexts))  //compareAndSet是compareAndSwap的变体,它的返回值是true/false,代表本操作是否成功地修改了某变量
                return s % n;
        }
    }
}

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.