在JDK并发包提供了几个常用的并发工具类:CountDownLatch、CyclicBarrier、Semaphore提供了一种并发流程控制的手段,而Exchanger工具类提供了在线程间交换数据的一种手段。
CountDownLatch允许一个或多个线程等待其他线程完成操作。
CountDownLatch和CyclicBarrier的区别
- CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许一组线程相互等待。
- CountDownLatch的计数器无法被重置,只能使用一次;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier,能处理更为复杂的业务场景。
- CountDownLatch通过自定义同步器(共享锁)实现的;而CyclicBarrier是通过重入锁ReentrantLock(排他锁)和Condition来实现的。
源码分析
依赖
CountDownLatch是通过自定义同步器以实现共享锁来完成await()
和countDown()
操作的。
CountDownLatch的await方法可以在多个线程中调用,当CountDownLatch的计数器为0后,调用await的方法都会依次返回。 也就是说可以多个线程同时在等待await方法返回,所以获取的是一个共享锁。
|
|
构造方法
构造方法接收一个int类型的参数作为计数器,并初始化自定义的同步器。
await()
|
|
acquireSharedInterruptibly()
的作用是获取共享锁。
如果当前线程是中断状态,则抛出异常InterruptedException
。否则,调用tryAcquireShared(arg)
尝试获取共享锁;尝试成功则返回,否则就调用doAcquireSharedInterruptibly()
。doAcquireSharedInterruptibly()
会使当前线程一直等待,直到当前线程获取到共享锁(或被中断)才返回。
countDown()
|
|
releaseShared()
目的是让当前线程释放锁,首先会通过tryReleaseShared()
去尝试释放共享锁。尝试成功,则直接返回;尝试失败,则通过doReleaseShared()
去释放共享锁。
实例
老板等几个工人做完事后再来检验工作情况,每个工作进行一次countDown()
,老板则执行await()
进行等待。
可以有多个老板同时await()
一起完成检验工作,这个时候需要用到共享锁。