zoukankan      html  css  js  c++  java
  • java8 如何优化CAS的性能

      场景引入

        经常都会有下面这段代码,多个线程同时修改一个变量,造成线程不安全,代码如下:

    public class ThreadCASDemo implements Runnable {
        static int counter=0;
        static  final Object objLock=new Object();
    
        @Override
        public  void run() {
            counter++;
            System.out.println("counter"+counter);
        }
    
        public static void main(String[] args) {
            for (int i = 0; i <20 ; i++) {
                ThreadCASDemo threadCASDemo=new ThreadCASDemo();
                Thread th=new Thread(threadCASDemo);
                th.start();
            }
            try {
                Thread.sleep(2000);
            }
            catch (Exception ex){
    
            }
            System.out.println(counter);
        }
    }

      解决方案

        加synchronized锁

    public class ThreadCASDemo implements Runnable {
        static int counter=0;
        static  final Object objLock=new Object();
    
        @Override
        public  void run() {
            synchronized (objLock) {
                counter++;
            }
            System.out.println("counter"+counter);
        }
    
        public static void main(String[] args) {
            for (int i = 0; i <20 ; i++) {
                ThreadCASDemo threadCASDemo=new ThreadCASDemo();
                Thread th=new Thread(threadCASDemo);
                th.start();
            }
            try {
                Thread.sleep(2000);
            }
            catch (Exception ex){
    
            }
            System.out.println(counter);
        }
    }

        加synchronized锁的原理示意图如下:

        

        一个个线程排队去更新这个值,这样就感觉太笨重了。synchronized是用来解决更复杂的并发编程场景的。

        而且在这个场景下,你一个个排队,加锁处理数据,释放锁,下一个再进来不就相当于串行化了吗。

        Atomic原子类

    public class ThreadCASAtomic implements Runnable {
        static AtomicInteger ati=new AtomicInteger(0);
        static  final Object objLock=new Object();
    
        @Override
        public  void run() {
            Integer counter=ati.incrementAndGet();
            System.out.println("counter"+counter);
        }
    
        public static void main(String[] args) {
            for (int i = 0; i <20 ; i++) {
                ThreadCASDemo threadCASDemo=new ThreadCASDemo();
                Thread th=new Thread(threadCASDemo);
                th.start();
            }
        }
    }

        这个之所以效率更高,因为底层是无锁化的CAS。(Compare And Set)。

        底层原理如下:每个线程都会先获取当前的值,接着走一个CAS操作,原子的意思就是这个CAS操作一定是自己完整执行完的,不会被别人打断的。

        然后CAS操作里,会比较一下说:大兄弟,现在你的值不是我刚刚才获取到的那个值啊?

        如果是的化,说明没人改过这个值,那你就给我设置累加1的操作,如果不是的话,发现自己获取的值跟当前的值不一样,会导致CAS失败,失败之后,进入一个无线循环,再次获取值,进行CAS操作。

      Java 8 中对CAS机制的优化

        上面的做法问题就出现在,如果大量的线程同时并发修改一个AtomicInteger,可能会有很多线程,不停的自旋,进入一个无线的重复循环中。

        这些线程不停的获取值,不停的失败。

        在高并发的时候,这种情况就会很明显,导致性能和效率都不高。

        所以java 8 提出了一个LongAdder,他就是尝试使用分段CAS以及自动分段迁移的方式来大幅度提高多线程高并发执行CAS的操作性能。  

        

      

                

    终极目标:世界大同
  • 相关阅读:
    使用 DataAdapter 执行批量更新 [摘自MSDN]
    深入浅出net泛型编程
    模版页中引用文件路径的问题
    查询SQLSERVER某个表所占用空间大小的SQL语句
    如何获取SQL Server数据库里表的占用容量大小的存储过程
    确定计算机是否可以运行 Windows Vista? 操作系统
    SQL语句 [转]
    SQLServer中如何将一个字段的多个记录值合在一行显示
    ASP.net在页面所有内容生成后、输出内容前对页面内容进行操作
    oracle 删除用于及其表空间
  • 原文地址:https://www.cnblogs.com/gdouzz/p/14465666.html
Copyright © 2011-2022 走看看