免费html网站登录模板,263企业邮箱怎么注册,郑州seo线上推广技术,wordpress 显示标题AQS#xff08;AbstractQueuedSynchronizer#xff09;是 Java 中的一个强大的同步框架#xff0c;为我们提供了实现各种同步器的基础。在本篇博客中#xff0c;我们将介绍 AQS 框架的基本原理#xff0c;并探讨几个常见的 AQS 实现#xff1a;ReentrantLock、CountDownL…AQSAbstractQueuedSynchronizer是 Java 中的一个强大的同步框架为我们提供了实现各种同步器的基础。在本篇博客中我们将介绍 AQS 框架的基本原理并探讨几个常见的 AQS 实现ReentrantLock、CountDownLatch 和 Semaphore。我们将了解它们的区别以及各自的优缺点。
1. AQS 框架简介
AQS 是 Java 并发包中的核心部分它提供了一个基于 FIFOfirst in first out 先进先出排队的双向链表等待队列用于管理等待线程并控制资源的获取和释放。AQS 提供了一些核心的方法供子类继承和实现。下面我们重点介绍几个常见的 AQS 实现。
2. AQS 框架适用场景
AQS 用于单个服务内部的线程同步和并发控制。适用于所有单体架构或者微服务项目中单个服务内部的线程同步和并发控制。不适用于分布式部署项目对于集群部署的微服务项目需要额外考虑跨服务的分布式同步问题并选择适合的分布式锁解决方案来实现分布式环境下的同步与控制。例如 ZooKeeper、Redisson 等提供的分布式锁实现
3. ReentrantLock可重入锁
ReentrantLock 是 AQS 框架的一个常见应用它提供了独占模式的锁。多个线程可以重复获取和释放该锁而不会因为重复获取而发生死锁。这个特性使得 ReentrantLock 可以用于更复杂的同步场景。
ReentrantLock内部使用了一个int变量来表示锁的持有状态,作为条件是占用资源,值为0时表示未锁定状态,大于0表示已锁定。
下面是一个简单的示例代码
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {private static ReentrantLock lock new ReentrantLock();public static void main(String[] args) {lock.lock(); // 加锁如果没有线程持有则持有数加1返回。如果有线程持有则持有数加1并放到aqs等待队列排队try {// 执行保护的代码块} finally {lock.unlock(); // 释放锁如果当前线程是此锁的持有者则持有计数递减。如果保持计数现在为零则释放锁。如果当前线程不是此锁的持有者则抛出IllegalHonitorStateException}}
}ReentrantLock 的优点是提供了可重入性支持公平和非公平模式并且具有更丰富的功能。缺点是相对于 synchronized 关键字有更高的复杂性和更多的开销。
4. CountDownLatch倒计时门栓
CountDownLatch 是一个同步机制,它允许一个或多个线程等待其他线程完成操作,它的构造器将会接收一个整数参数,表示需要等待的线程数量。
CountDownLatch内部也使用AQS的等待队列实现等待线程的阻塞,使用一个int类型的计数器来表示需要等待的线程数。
具体实现过程:
构造时将计数器初始化为传入的参数值。
countDown()方法会让计数器值减1,如果计数器变为0了,则唤醒等待队列中所有的线程
await()方法会首先将当前线程添加到AQS的等待队列中,然后判断计数器是否为0,如果不为0则一直等待。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {private static CountDownLatch latch new CountDownLatch(3);public static void main(String[] args) throws InterruptedException {// 创建并启动多个线程for (int i 0; i 3; i) {new Thread(() - {// 执行操作latch.countDown(); // 操作完成后计数减1}).start();}latch.await(); // 等待计数为0// 所有操作完成后继续执行}
}CountDownLatch 的优点是简单易用可以很方便地实现等待其他线程完成的场景。缺点是一旦计数值确定后就无法修改并且只能使用一次。
5. Semaphore信号量
Semaphore 是一种控制并发访问资源数量的同步工具。它允许多个线程同时访问共享资源但需要限制总的访问线程数量。Semaphore 通过 AQS 的计数和等待机制来控制线程的获取和释放。
Semaphore内部也是通过一个int值表示许可数量来实现的 acquire()方法会获取一个许可,如果没有就排队等待; release()方法会释放一个许可。
下面是一个简单的示例代码
import java.util.concurrent.Semaphore;
public class SemaphoreExample {private static Semaphore semaphore new Semaphore(2);public static void main(String[] args) {// 创建并启动多个线程for (int i 0; i 5; i) {new Thread(() - {try {semaphore.acquire(); // 获取许可// 访问共享资源} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release(); // 释放许可}}).start();}}
}Semaphore 的优点是可以控制资源的并发访问数量可以用于限流等场景。缺点是相对于其他同步机制有更多的复杂性和开销。
总结
锁定对象:
ReentrantLock是一种互斥锁,用于保护共享资源免受并发访问的侵害。CountDownLatch和Semaphore不是用来进行同步互斥的,CountDownLatch用来协调并行任务。Semaphore用来控制对共享资源的访问数量。
实现原理:
ReentrantLock使用状态变量表示锁的可重入性。CountDownLatch使用状态计数器,计数到0为0后释放所有等待线程。Semaphore使用许可证计数来控制可以访问的线程数量。
使用场景:
ReentrantLock用于同步访问的临界区。CountDownLatch用于等待一组异步任务完成。Semaphore用于控制对某种资源的并发数量。