原理解析!原子操作CAS及其实现类

享学课堂特邀作者:潇湘夜雨

转载请声明出处!

什么是原子操作

原子的意思是说“不能被进一步分割的粒子”,而原子操作是说“不可被终端的一个或多个系列的操作”。假定有两个操作A和B,如果从执行A的线程来看,当另一个线程执行B时,要么将B全部执行完,要么完全不执行B,那么A和B对彼此来说是原子的。

java中可以通过锁,锁机制的方式来实现原子操作,但是有时候需要更有效灵活的机制,synchronized关键字是基于阻塞的锁机制,也就是说当一个线程拥有锁的时候,访问同一资源的其它线程需要等待,直到该线程释放锁,因为synchronized关键字具有排他性,如果有大量的线程来竞争资源,那CPU将会花费大量的时间和资源来处理这些竞争,同时也会造成死锁的情况。而且锁的机制相当于其他轻量级的需求有点过于笨重,例如计数器,这个后边我会介绍两者之间的性能的比较。

如何实现原子操作

实现原子操作还可以使用CAS实现原子操作,利用了处理器提供的CMPXCHG指令来实现的,每一个CAS操作过程都包含三个运算符:一个内存地址V,一个期望的值A和一个新值B,操作的时候如果这个地址上存放的值等于这个期望的值A,则将地址上的值赋为新值B,否则不做任何操作。
CAS的基本思路就是,如果这个地址上的值和期望的值相等,则给其赋予新值,否则不做任何事,但是要返回原值是多少。循环CAS就是在一个循环里不断的做cas操作,直到成功为止。下面的代码实现了一个CAS线程安全的计数器safeCount。

public class Counter {
    private AtomicInteger atomicCount = new AtomicInteger(0);
    private int i = 0;

    /** cas cafecount **/
    private void safeCount() {
        for (; ; ) {
            int i = atomicCount.get();
            boolean suc = atomicCount.compareAndSet(i, ++i);
            if (suc) {
                break;
            }
        }
    }

    public static void main(String[] args) {
        Counter cas = new Counter();
        List ts = new ArrayList<>(500);
        long start = System.currentTimeMillis();
        for (int j = 0; j < 100; j++) {
            Thread t = new Thread(() -> {
                for (int i = 0; i < 10000; i++) {
                    cas.safeCount();
                }
            });
            ts.add(t);
        }
        for (Thread t : ts) {
            t.start();
        }
        for (Thread t : ts) {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(cas.i)

你可能感兴趣的:(程序员,java,经验分享,面试)