CAS底层实现

作者: Matures | 来源:发表于2021-01-02 14:48 被阅读0次

    先从一段代码开始

        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的原子性

    相关文章

      网友评论

        本文标题:CAS底层实现

        本文链接:https://www.haomeiwen.com/subject/wmreoktx.html