札记CAS、AQS、CountDownLatch、CountDownLatch、CyclicBarrier的原理

经常会被人问到CAS的原理、AQS的原理,CountDownLatch的原理,CyclicBarrier的原理!时间久了,就可能慢慢忘了,但是我们在编程的时,在用到的时候可以快速的浏览一下,于是就又记起来了。这里我把它记录起来,便于在自己闲暇时刻浏览阅读。

CAS的原理

CAS的英文是Compare and Swap,中文意思是比较并交换。JUC包中借助CAS实现了区别于synchronized同步锁的一种乐观锁。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。重点来了,CAS的原理:CAS通过调用JNI的代码实现的。JNI:Java Native Interface为JAVA本地调用,允许Java调用其他语言(C)。很多实现原子性操作的调用,都是依赖于sun.misc.Unsafe类。比如:compareAndSwapInt()方法就是借助C来调用CPU底层指令实现的。

AQS的原理

AQS(AbstractQueuedSynchronizer)是JDK1.5提供的一个基于FIFO等待队列实现的一个用于实现同步器的基础框架,这个基础框架的重要性可以这么说,JUC包里面几乎所有的有关锁、多线程并发以及线程同步器等重要组件的实现都是基于AQS这个框架。AQS的核心思想是基于volatile int state这样的一个属性同时配合Unsafe工具对其原子性的操作来实现对当前锁的状态进行修改。当state的值为0的时候,标识该Lock不被任何线程所占有。

CountDownLatch的原理

实现原理:计数器的值由构造函数传入,并用它初始化AQS的state值。当线程调用await方法时会检查state的值是否为0,如果是就直接返回(即不会阻塞);如果不是,将表示该节点的线程入列,然后将自身阻塞。当其它线程调用countDown方法会将计数器减1,然后判断计数器的值是否为0,当它为0时,会唤醒队列中的第一个节点,由于CountDownLatch使用了AQS的共享模式,所以第一个节点被唤醒后又会唤醒第二个节点,以此类推,使得所有因await方法阻塞的线程都能被唤醒而继续执行

CyclicBarrier的原理

实现原理:在CyclicBarrier的内部定义了一个Lock对象,每当一个线程调用CyclicBarrier的await方法时,将剩余拦截的线程数减1,然后判断剩余拦截数是否为0,如果不是,进入Lock对象的条件队列等待。如果是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列中,这些线程会依次的获取锁、释放锁,接着先从await方法返回,再从CyclicBarrier的await方法中返回。

比较CountDownLatch和CyclicBarrier的区别

1 CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待

2 CountDownLatch的计数器到0无法被重置;CyclicBarrier的计数器可以被循环使用,因此它被称为是循环的屏障

总结

要学习好Java并发基础,并清楚其原理,还是要多阅读源码,学习Java虚拟机内存模型(JMM)以及Java的内存管理模型。其实会发现很多时候底层都是调用了JNI接口,而很多并发容器都实现了AQS(模板方法模式)。

参考资料

1 Doug Lea Java并发编程实践

2 方腾飞 Java并发编程的艺术

3 Hsuxu的博客 https://blog.csdn.net/hsuxu/article/details/9467651

4 大明哥 死磕系列博客地址: http://cmsblogs.com/

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180330G0N6OM00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券