java并发CountDownLatch基本使用和源码解读
CountDownLatch是一个并发编程里面常用的类,行业里面叫“发令枪”。
个人理解:当要去执行这一行代码的时候,必须等到其他线程执行完毕以后,才能去执行该代码。这个时候就可以使用CountDownLatch。
1:代码的实现
public class CountDownLatchTest { static CountDownLatch latch = new CountDownLatch(5); public static class InitThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+ "==========>>init start......"); latch.countDown(); System.out.println(Thread.currentThread().getName()+ "==========>>init complate......"); } } public static void main(String[] args) throws InterruptedException { System.out.println(Thread.currentThread().getName()+ "========>>Thread main start"); for (int i=0;i<5;i++){ Thread thread = new Thread(new InitThread()); thread.start(); } latch.await(); System.out.println(Thread.currentThread().getName()+ "========>>Thread main end"); } }
运行结果

解释一下:当main方法执行到latch.await方法的时候,一直在这里等待,直到有别的线程执行完了 latch.countDown 减为0,继续执行。
latch.countDown在 new CountDownLatch(5) ,在5的基础上 每次都会减1,调用一次就会减1,直到减为0。
以上就是个人对CountDownLatch简单的使用说明。
2:第二部分就是对CountDownLatch源码的解析
CountDownLatch的底层是基于AQS实现的,如果对AQS没有了解的,请先去了解AQS的原理,底层也会涉及到CAS的一些原理。
如下是CountDownLatch类中的属性和方法。Sync继承了AbstractQueuedSynchronizer

Sync类的说明,在AQS当中,用state这个字段来标识是否获取到了锁,当我们调用new CountDownLatch(5),其实调用的是Sync的构造函数,构造函数给state设置初始值。


当我们调用countDown方法的时候,其实是调用的sync.releaseShard方法,但是在sync类中没有该方法,那方法就只能在父类(AbstractQueuedSynchronizer)中了。
父类当中releaseShared方法,tryReleaseShared方法 是protected修饰的 一个模板的方法,会执行子类的。所以又调用到了sync类中的tryReleaseShared。
该方法 是一个死循环 首先获取state的值,如果是0返回的是false。如果不是0,会在state基础上进行减1的操作,通过CAS的机制保证操作正确,如果CAS不成功,就继续从头开始循环。当如果减到为0的时候,就返回TRUE。
当tryReleaseShared返回TRUE的时候,执行源代码中的doReleaseShared方法。因为没有涉及到加入到同步队列,所以就直接执行到最后break到for循环。




总结一下:countDown方法就是给state一直进行减1的操作,知道操作到等于0。
await方法,acquireSharedInterruptibly方法在sync类中没有,说明在父类(AbstractQueuedSynchronizer)中了。
首先判断当前是否终止了,调用了interrupted方法,如果终止了则抛出异常,如果没有终止,继续调用tryAcquireShared方法,该方法是一个protected修饰的,说明是一个模板方法。
具体实现在sync类中tryAcquireShared方法,该方法判断state是否为0,是0返回1,不是返回-1。当返回-1的时候,会执行doAcquiredSharedInterruptibly。
有一个死循环,会重新调用tryAcquireShared方法,如果大于0就返回,小于0就继续循环,直到大于0才退出。




当线程调用了await方法,就会进入一个死循环,一直再调用。直到state等于才退出。
注:doReleaseSharedInterruptibly、doAcquiredSharedInterruptibly方法是AQS的方法,我会在AQS的源码当中进行重点的解析。
以上就是本人对CountDownLatch的基本使用和源码解析。如果有不对的地方,还希望大家指出。谢谢!

浙公网安备 33010602011771号