多线程之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

posted on 2020-03-11 16:59  黑子菜园  阅读(820)  评论(0编辑  收藏  举报

导航