AQS(AbstractQueuedSynchronizer)是一个用于实现各种同步器的抽象类,是 JUC(java.util.concurrent)并发包中的核心类之一,JUC 中的许多并发工具类和接口都是基于 AQS 实现的。它提供了一种基于队列的、高效的、可扩展的同步机制,是实现锁、信号量、倒计时器等同步器的基础。
同步器:同步器指的是用于控制多线程访问共享资源的机制。同步器可以保证在同一时间只有一个线程可以访问共享资源,从而避免了多线程访问共享资源时可能出现的数据竞争和不一致性问题。Java 中的同步器包括 synchronized 关键字、ReentrantLock、Semaphore、CountDownLatch 等。
核心思想
AQS 的核心思想是利用一个双向队列来保存等待锁的线程,同时利用一个 state 变量来表示锁的状态。AQS 的同步器可以分为独占模式和共享模式两种。独占模式是指同一时刻只允许一个线程获取锁,常见的实现类有 ReentrantLock;共享模式是指同一时刻允许多个线程同时获取锁,常见的实现类有 Semaphore、CountDownLatch、CyclicBarrier 等。
资源共享模式
AQS 中资源共享模式分为两种:
- 独占模式:AQS 维护了一个同步队列,该队列中保存了所有等待获取锁的线程。当一个线程尝试获取锁时,如果锁已经被其他线程持有,则将该线程加入到同步队列的尾部,并挂起线程,等待锁被释放。当锁被释放时,从同步队列中取出一个线程,使其获取锁,同时将它从队列中移除,唤醒该线程继续执行。独占模式又分为公平锁和非公平锁:
- 公平锁:按照线程在队列中的排队顺序,先到者先拿到锁;
- 非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的。
- 共享模式:AQS 维护了一个等待队列和一个共享计数器。共享计数器表示当前允许获取锁的线程数,当一个线程尝试获取锁时,如果当前允许获取锁的线程数已经达到了最大值,则将该线程加入到等待队列中,并挂起线程,等待其他线程释放锁或者共享计数器增加。当锁被释放时,会从等待队列中取出一个线程,使其获取锁,同时将它从队列中移除,唤醒该线程继续执行。
AQS 提供了一些方法,允许我们在自定义同步器中使用 AQS 的同步机制。其中包括 acquire()、release()、tryAcquire()、tryRelease() 等方法,这些方法的具体实现会因同步器的不同而有所区别。
小结
AQS 是 Java 并发编程中非常重要的一个类,它提供了基础的同步机制,可以实现各种同步器,并为高级的并发工具类和接口提供支持。熟练掌握 AQS 的使用,对于编写高效、线程安全的并发程序是非常有帮助的,JUC(java.util.concurrent)中的许多并发工具类和接口都是基于 AQS 实现的。
特殊说明
以上内容来自我的《Java 面试突击训练营》,这门课程是有着十几年工作经验(前 360 开发工程师),10 年面试官经验的我,花费 4 年时间打磨完成的一门视频面试课。学完训练营的课程之后,基本可以应对目前市面上绝大部分公司的面试了,并且课程配备了 9 大就业服务,帮助上千人找到 Java 工作,其中上百人拿到大厂 Offer,学员最高薪资 70W 年薪,面试课目录和 9 大服务如下:
加我微信咨询:vipStone【备注:训练营】