CAS底层实现

先从一段代码开始

    private static AtomicInteger a = new AtomicInteger(0);

    private static int anInt = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[100];

        for (int i = 0; i < threads.length ; i++) {
            threads[i] = new Thread(()->{
                for (int j = 0; j < 1000; j++) {
                    a.incrementAndGet();
                    anInt++;
                }
            });
            threads[i].start();
        }
        Thread.sleep(100);
        System.out.println("原子类:"+a.get());
        System.out.println("基本数据类型int:"+anInt);
    }

其结果如下

原子类:100000
基本数据类型int:63516

原子了每次运行的结果都能达到预期,而int基本无法达到。
查看incrementAndGet()方法源码

public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

定位到Unsafe.class

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

在回写到内存时,比较期望值,若发生改变则重新读取变量再执行一次操作。这即是比较并交换的思想:CAS (compareAndSwap)
那么在这个过程中必然涉及的两个问题:
1、期望值会不会是多个线程多次回写的结果,导致期望值相等?
2、在判断期望值相等的一瞬间,会不会有线程将变量的值修改?
对于问题一,加上版本号即可解决。至于问题二,则需要查看C++代码,最终在C++代码中找到实现

lock cmpxchg 指令

lock指令在执行后面指令的时候锁定一个北桥信号,任何线程都得等我执行完才能执行,这样就保证了CAS的原子性

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容