CountDownLatch
、CyclicBarrier
和Semaphore
是Java并发包java.util.concurrent
中提供的三种同步辅助工具,它们用于控制线程间的协调。
CountDownLatch
CountDownLatch
是一个同步辅助工具,它允许一个或多个线程等待一组操作完成。
原理:
- 它内部维护一个计数器,初始值由构造函数传入。
- 通过
countDown()
方法递减计数器。 - 通过
await()
方法阻塞等待计数器归零。
就像一场赛车比赛,裁判(主线程)在等待所有赛车(工作线程)都到达终点(countDown()
)后才能宣布比赛结束(await()
)。
使用场景:
- 用于某个固定时刻只有当所有任务都执行完毕后,才能继续执行后续的任务。
CyclicBarrier
CyclicBarrier
是一个同步辅助工具,它允许一组线程相互等待,直到所有线程都到达某个公共屏障点。
原理:
- 它内部同样维护一个计数器,当线程到达屏障时计数器递减。
- 线程调用
await()
方法时,如果计数器还没到零,则线程会被阻塞。 - 当所有线程都到达屏障点后,计数器归零,所有线程都会被唤醒。
就像一群朋友约定在某个地方集合,所有人到齐后才能一起出发去下一个目的地。
使用场景:
- 用于需要周期性执行的任务,比如多线程分批处理数据。
Semaphore
Semaphore
是一个计数信号量,用于限制对资源的访问。
原理:
- 它内部维护一个许可集合,线程可以通过
acquire()
方法获取许可。 - 如果没有许可,则线程会被阻塞。
- 线程使用完毕后,通过
release()
方法释放许可。
就像一个停车场,有固定数量的停车位,车辆(线程)需要先获取停车许可(acquire()
)才能停车,离开时释放停车位(release()
)。
使用场景:
- 用于限制对资源的并发访问数量,比如数据库连接池。
区别
用途:
CountDownLatch
用于一次性操作,不能重用。CyclicBarrier
可以重复使用,适用于多次的同步操作。Semaphore
用于控制资源的并发访问。
功能:
CountDownLatch
只能减少计数,不能增加。CyclicBarrier
可以在每次完成后重置计数。Semaphore
的计数可以增加也可以减少。
灵活性:
CountDownLatch
一旦构造,计数就固定了。CyclicBarrier
和Semaphore
在运行时可以动态地获取和释放许可。
阻塞策略:
CountDownLatch
和CyclicBarrier
在计数器未达到条件时会阻塞线程。Semaphore
在没有许可时会阻塞线程。
这些工具在并发编程中非常有用,它们帮助开发者控制线程间的协作和同步,以确保程序的正确性和性能。