原子类与CAS

JUC包下的原子类是CAS算法运用的典范

 

1.引入(线程安全的累加器)

我们来看平常的一个累加器

public class AutomicDemo {



   private static  AtomicInteger count = new AtomicInteger();
   public  void add() {
      for (int i = 0; i < 1000; i++) {
        count.addAndGet(1);
      }
   }
   public static AtomicInteger result() throws InterruptedException {

      //创建两个线程,执行累加器

      AutomicDemo demo = new AutomicDemo();
      Thread threadOne = new Thread(() -> {
        demo.add();
      });

      Thread threadTwo = new Thread(() -> {
        demo.add();
      });

      threadOne.start();
      threadTwo.start();
      threadOne.join();
      threadTwo.join();
      return count;
   }

   public static void main(String[] args) throws InterruptedException {

      // TODO Auto-generated method stub

      AtomicInteger result = AutomicDemo.result();

      System.err.println("最终的运算结果是:" + result);

   }

}

以上程序使用了原子类并不会发生线程安全问题。那原子类是怎么保证线程安全的呢?它的实现方式并不是加锁,而是使用了CAS算法(check and swap)。

2.CAS介绍

CAS相对与互斥锁方案,最大的优点就是性能。互斥锁为了达到互斥的目的操作前后都要有加锁解锁。这样性能损耗很大,而CAS采用无锁的方式达到了互斥的效果,性能相对而言较高。

 

那么原子类中的CAS怎么实现的呢,这也要依靠硬件的支持,CAS指令有三个参数(共享变量的地址A,用于比较的变量B 更新的新值C),只有当A=B时候,将A处的值更新为C。作为一条CPU指令,CAS指令本身是可以保证原子性的。

3.Java模拟CAS算法

(当然CAS底层不是通过synchronized实现的,这里只是为了便于理解,理解逻辑就行)

class SimpleCAS{

   public volatile int count;

 
   /**

    * 模拟CAS的更新值过程

    * @param exceptValue

    * @param newValue

    * @return

    */

   public synchronized int cas(int exceptValue, int newValue){

      //读取当前的值
      int currentValue = count;
      //如果当前值与预期值相等就赋新值,否则不变
      if(currentValue == exceptValue){
        count = newValue;
      }
      return currentValue;

   }

  

   /**

    * 模拟自旋过程(如果与可预期值不相等,会不断尝试)

    * @return

    */

   public synchronized void addOne(){
      int newValue ;
      do{
         newValue = count + 1;
      }while(count != cas(count, newValue));

   }

}

 

CAS算法会出现的问题

  1. ABA问题,也就是加入之前的值的变化是 1-2-1,最后还是1,那么就会和exceptValue相等,这样会出现问题,解决的方式是增加一个版本号,由于版本号是递增的,每次变化都不一样,每次更新值之前还要检查一下版本号
  2. 不断自旋
发布了29 篇原创文章 · 获赞 34 · 访问量 8154

猜你喜欢

转载自blog.csdn.net/weixin_39634532/article/details/91140436