为了账号安全,请及时绑定邮箱和手机立即绑定

Java多线程(5):CAS

标签:
Java

您好,我是湘王,这是我的慕课手记,欢迎您来,欢迎您再来~



JDK1.5之前,Java的多线程都是靠synchronized来保证同步的,这会引起很多性能问题例如死锁但随着Java的不断完善,JNI(Java Native Interface)使得Java能越过JVM直接调用本地方法例如CAS

CAS是Compare And Swap(比较与交换)的缩写,它用于实现多线程同步的原子指令,允许算法执行读-修改-写操作,而无需担心其他线程同时修改变量说人话意思就是它的操作过程足够细微以至于线程都奈何不了它

所谓原子指令就是指不会被线程调度机制打断的操作指令,这种操作一旦开始,就一直运行到结束,中间不会有任何线程切换,即要么全部完成,要么全部中断换一种说法就是CAS可以保证Java运算实现我们想要的操作而无需担心会受到多线程的影响

某种程度上,CAS可以用来取代synchronized的强制同步,提升性能其实整个java.util.concurrent包都是建立在CAS之上的,尤其是Java中大多数锁的实现基类AbstractQueuedSynchronizer,更是以CAS为基础,提供了一系列的独占锁、共享锁、可重入锁、自旋锁、读写锁等多线程控制手段这在后面会说)。就像图中那样

https://img1.sycdn.imooc.com//635aa47c000169fb10120550.jpg

 

Java对CAS的实现都在java.util.concurrent.atomic包下java.util.concurrent也简称JUC这是个简称所以如果有面试官说想让你谈谈JUC相关的问题不要一脸懵否则会被立即淘汰)。AtomicInteger为例,从源码可以看出CAS操作都是通过sun包下Unsafe类实现,而Unsafe类中的方法都是native方法,由本地实现,和操作系统、CPU都有关系CAS有一个比较通用的实现模式:

1、首先声明(共享)变量为volatile

2、然后使用CAS的原子条件来更新

3、同时配合volatile的可见性来实现线程之间的同步

前面讲过不用深究volatile关键字的用途因为随着机器配置的豪华其实这个关键字已经没啥用了而且也可以看到CAS里面也有大量出现JDK已经替你用好了自己如果不太熟悉就不要用了CAS相关类结构图是

https://img1.sycdn.imooc.com//635aa48600010b1213550583.jpg


还是老规矩用代码来举例

/**
 * 仅用AtomicInteger实现CAS
 *
 * @author 湘王
 */
public class AtomicIntegerTester1 {
   // 使用AtomicInteger实现CAS,有没有volatile都不影响
   public static volatile AtomicInteger atomicInteger = new AtomicInteger(0);

   public static void main(String[] args) throws InterruptedException {
      ExecutorService executor = Executors.newFixedThreadPool(3);

      for (int i = 0; i < 20; i++) {
         Runnable runnable = new Runnable() {
            @Override
            public void run() {
               atomicInteger.getAndIncrement();
            }
         };
         executor.submit(runnable);
      }

      // 为了观察效果休眠,但实际生产环境中肯定不允许
      Thread.sleep(100);
      executor.shutdown();
      System.out.println(atomicInteger.get());
   }
}



/**
 * 用AtomicIntegerFieldUpdater实现CAS
 *
 * @author 湘王
 */
public class AtomicIntegerTester2 {
   /*
    * 使用AtomicIntegerFieldUpdater实现CAS,相关计算字段必须用volatile修饰,不然抛异常
    * Caused by: java.lang.IllegalArgumentException: Must be volatile type
    *
    */
   public volatile int count = 0;
   public static final AtomicIntegerFieldUpdater<AtomicIntegerTester2> lockUpdate = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerTester2.class, "count");

   public int increase(int inc) {
      return lockUpdate.addAndGet(this, inc);
   }

   public int get() {
      return lockUpdate.get(this);
   }

   public static void main(String[] args) throws InterruptedException {
      AtomicIntegerTester2 tester = new AtomicIntegerTester2();
      ExecutorService executor = Executors.newFixedThreadPool(3);
      for (int i = 0; i < 20; i++) {
         Runnable runnable = new Runnable() {
            @Override
            public void run() {
               tester.increase(1);
            }
         };
         executor.submit(runnable);
      }
      // 为了观察效果休眠,但实际生产环境中肯定不允许
      Thread.sleep(100);
      executor.shutdown();
      System.out.println(tester.get());
   }
}



CAS的内容并不多可以看看它的源码还是比较有意思的

 


 

感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消