常见并发工具类的使用场景
常见并发工具类的使用场景
ReentrantLock
ReentrantLock是一种可重入的独占锁,它允许同一个线程多次获取同一把锁而不会被阻塞。它的功能类似于synchronized是一种互斥锁,可以保证线程安全。
- 可中断
- 可以设置超时时间
- 可以设置为公平锁
- 支持多个条件变量
- 与 synchronized 一样,都支持可重入
主要应用场景:多线程环境下对共享资源进行独占式访问,以保证数据的一致性和安全性。当然我们也可以使用ReentrantLock和Condition实现生产者消费者模式,向ArrayBlockingQueue底层存元素和取元素就是借助ReentrantLock和Condition来实现的。
作为可重入锁常常应用于递归操作、调用同一个类中的其他方法、锁嵌套等场景中。
解决多线程竞争资源的问题,例如多个线程同时对同一个数据库进行写操作,可以使用ReentrantLock保证每次只有一个线程能够写入。
实现多线程任务的顺序执行,例如在一个线程执行完某个任务后,再让另一个线程执行任务,主要借助于ReentrantLock的公平锁来实现。
实现多线程等待/通知机制,例如在某个线程执行完某个任务之后,通知其他线程继续执行任务,主要是借助于ReentrantLock和Condition来实现的。
Semaphore
Semaphore是信号量的意思,常用于并发编程中。用于控制同时访问某个资源的线程数量。Semaphore维护了一个计数器,线程可以通过acquire方法来获取许可证,可以通过release方法来释放许可证。当许可证数量为0的时候,再来线程将被阻塞。
Semaphore底层也支持公平锁和非公平锁。当使用公平锁的时候,下一个被执行任务的线程一定是等待时间最久的那个线程。
应用场景:
限流:Semaphore可以用于限制对共享资源的并发访问数量,以控制系统的流量。
资源池:Semaphore可以用于实现资源池,以维护一组有限的共享资源。
CountDownLatch
CountDownLatch是门栓的意思,常用于并发编程中,它可以让多个线程都阻塞在一个地方,直到所有线程任务都执行完成。
常用方法:countDown方法和await方法。
应用场景:
并行任务同步:CountDownLatch用于协调多个并行任务的完成情况,确保所有任务都完成后再继续执行下一步操作。
多任务汇总:CountDownLatch可以用于统计多个线程的完成情况,以确定所有线程都以完成工作。
资源初始化:CountDownLatch可以用于等待资源的初始化完成,以边在初始化完成后开始使用。
CountDownLatch可以阻塞主线程,适用于需要同步返回的接口
CyclicBarrier
CyclicBarrier是循环栅栏的意思,他的特点是可以循环使用,当多个线程都到达同一个指定点的时候,再同时执行。
应用场景:CyclicBarrier可以用于将复杂的任务分配给多个线程执行,并在所有线程完成工作后触发后续的操作。
CyclicBarrier无法阻塞主线程,不适合在需要同步返回的接口中使用。CyclicBarrier适用于异步任务,尤其需要对子线程的执行结果做汇聚计算的更为适合,在大部分场景下,CountDownLatch能实现的功能,都能使用CyclicBarrier实现。
ReentrantReadWriteLock
ReentrantReadWriteLock是读写锁,常用于java编程中。它允许多个线程同时读取数据,但只允许一个线程写入数据。在某些情况下,比方说读多写少的场景中,使用这个类可以提高程序的性能和可靠性。
应用场景:主要用于读多写少的场景。比如:在数据库连接池中,多个线程可能需要同时访问数据库,但是只有一个线程能够执行写操作,如插入、更新或删除数据。使用reentrantreadwritelock可以在保证数据一致性的同时提高并发性能。
ThreadPoolExecutor
ThreadPoolExecutor线程池。ThreadPoolExecutor底层也有使用到ReentrantLock,比如在调用shutdown或shutdownnow或addworker方法的时候都有使用到ReentrantLock加锁。
应用场景:在实际项目开发中,当我们有异步任务要执行的时候,通常会使用多线程。
AQS
AQS 全名叫 AbstractQueuedSynchronizer 抽象队列同步器是 java.util.concurrent.locks 包下的⼀个抽象类,是 JUC 的核⼼
底层基于双向链表来实现。是一种多线程同步器,是juc包下lock锁的底层实现,像以上这些类的底层实现都是基于AQS来实现的。