• 多线程之CAS与synchronized的比较


    业务场景:需要实现一个支持并发的计数功能

    1、计数功能的基本实现是:

    public class  Increment{

      private int count = 0;

      public void add(){   count++;   }

    }

    2、以上实现在并发环境下是不安全的,故修改方案1是加锁synchronized

    public class  Increment{

      private int count = 0;

      public synchronized  void add(){   count++;   }

    }

    //悲观锁,加锁后只能有一个线程你执行++操作,其他线程需要等待

    //不会出现count计数不准确的问题,线程安全

    3、但是以上实现,会让线程串行化,排队等待获取锁、加锁、处理数据、释放锁,并发下显得不合理

    修改方案2是使用Java并发包concurrent下的Atomic原子类

    public class  Increment{

      private AtomicInteger count = new AtomicInteger();

      public synchronized void add(){

        count.incrementAndGet();

      }

    }

    //多个线程可以并发的执行AtomicInteger的incrementAndGet()方法,把count的值累加1并返回累加后最新的值

    //Atomic原子类底层用的是无锁化的CAS机制,保证多线程修改一个数值的安全性

    4、实现原理:

    (1)每个线程都会先获取当前的值,接着走一个原子的CAS操作,原子的意思就是这个CAS操作一定是自己完整执行完的,不会被别人打断;

    (2)在CAS操作里,比较一下,现在的值跟刚才我获取到的那个值,是否相等,是则说明没有人改过这个值,那么将它设置成累加1之后的一个值;

    (3)同理,若有人在执行CAS时,发现自己之前获取的值与当前的值不一样,说明有其他人修改了值,导致CAS失败,失败之后进入一个循环,再次获取值,再执行CAS操作。

    5、CAS的问题

    每次去比较的时候,都发现值被别人改了,就会进入无限重复的循环。大量线程高并发时相当于空循环,自旋转,性能和效率都不是特别好。

    Java8的新类LongAdder,尝试使用分段CAS以及自动分段迁移的方式来提升多线程高并发执行CAS操作的性能。核心思想是热点分离,类似concurrentHashMap

  • 相关阅读:
    POJ 1981 最大点覆盖问题(极角排序)
    POJ 1286 Pólya定理
    POJ 1830 高斯消元
    HDU 3364 高斯消元
    Educational Codeforces Round 42D. Merge Equals(STL)
    ZOJ 3955:Saddle Point(思维)
    POJ 3301:Texas Trip(计算几何+三分)
    SCUT 125 :笔芯回文(DP)
    ZOJ 3953:Intervals(优先队列+思维)
    Codeforces Gym101097I:Sticks (思维)
  • 原文地址:https://www.cnblogs.com/blackdd/p/12463517.html
Copyright © 2020-2023  润新知