【JAVA进阶篇教学】第十五篇:Java中AQS讲解 📅 发布时间:2026/8/31 4:14:05 👁 浏览次数: 博主打算从0-1讲解下java进阶篇教学今天教学第十五篇Java中AQS讲解。 在Java并发编程中AQSAbstractQueuedSynchronizer是一个重要的框架用于实现同步器和锁的基础。它提供了一种灵活的方式来实现各种同步器如ReentrantLock、Semaphore、CountDownLatch等。本文将深入探讨AQS的原理、实现方式以及如何使用它来构建自定义的同步器。目录一、前言二、AQS的原理三、AQS的使用* *一、前言----在 Java 中AQSAbstractQueuedSynchronizer是一个用于实现同步器的抽象类它提供了一种通用的机制来管理共享资源的访问。AQS 的主要作用是通过维护一个同步队列来实现对共享资源的同步访问避免了多线程访问共享资源时可能出现的竞态条件和死锁等问题。二、AQS的原理--------AQS是通过一个FIFO先进先出的队列来管理等待线程实现对共享资源的访问控制。它的核心思想是将状态的管理委托给了子类通过模板方法模式来实现同步器的具体逻辑。AQS内部维护了一个state变量表示同步状态以及一个双向链表来存放等待线程。AQS的主要实现包括两个部分状态管理和线程阻塞与唤醒。状态管理AQS通过getState()和setState(int newState)方法来管理同步状态同时提供了compareAndSetState(int expect, int update)方法来实现原子更新状态。* 线程阻塞与唤醒AQS通过enq(Node node)和addWaiter(Node mode)等方法将等待线程加入到等待队列中通过release(int arg)和unparkSuccessor(Node node)等方法来唤醒等待线程。AQS 的原理主要基于以下几个方面同步队列AQS 依赖内部的同步队列一个 FIFO 双向队列来完成同步状态的管理。当前线程获取同步状态失败时同步器会将当前线程以及等待状态等信息构造成为一个节点Node并将其加入同步队列同时会阻塞当前线程。当同步状态释放时会把首节点中的线程唤醒使其再次尝试获取同步状态。节点同步队列中的节点Node用来保存获取同步状态失败的线程引用、等待状态以及前一个节点和后一个节点。节点的属性类型与名称以及描述如下表所示属性类型名称描述Threadthread获取同步状态失败的线程intwaitStatus等待状态Nodeprev前一个节点Nodenext后一个节点状态变量AQS 使用两个原子状态变量来维护同步状态* state表示资源的状态可以用于表示锁的占用情况或者其他同步状态。* exclusiveOwnerThread表示当前占用锁的线程。AQS 的实现通过维护状态变量和同步队列确保了多线程对共享资源的访问是有序的避免了竞态条件和死锁等问题的出现。三、AQS的使用--------下面是一个简单的 AQS 使用示例演示了如何使用 AQS 来实现一个简单的锁 import java.util.concurrent.locks.AbstractQueuedSynchronizer; public class MyLock extends AbstractQueuedSynchronizer { Override protected boolean tryAcquire(int arg) { // 判断是否可以获取锁 if (getState() 0) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } } return false; } Override protected boolean tryRelease(int arg) { // 判断是否可以释放锁 if (getState() 1 getExclusiveOwnerThread() Thread.currentThread()) { setExclusiveOwnerThread(null); setState(0); return true; } return false; } public void lock() { acquire(1); } public void unlock() { release(1); } public static void main(String[] args) { MyLock lock new MyLock(); // 线程 1 获取锁 new Thread(() - { lock.lock(); try { System.out.println(“Thread 1 获取锁成功”); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println(“Thread 1 释放锁成功”); } }).start(); // 线程 2 获取锁 new Thread(() - { lock.lock(); try { System.out.println(“Thread 2 获取锁成功”); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println(“Thread 2 释放锁成功”); } }).start(); } }在上述示例中我们创建了一个名为MyLock的类它继承自AbstractQueuedSynchronizer。在MyLock类中我们重写了tryAcquire和tryRelease方法用于实现锁的获取和释放逻辑。 在main方法中我们创建了一个MyLock对象并启动了两个线程。每个线程在执行任务之前都需要先获取锁然后在任务执行完毕后释放锁。由于锁是互斥的所以只有一个线程能够同时获取锁。 通过使用 AQS我们可以方便地实现各种同步器如锁、信号量、栅栏等。AQS 的优点是通用性强、效率高、扩展性好可以满足不同场景下的同步需求。点下关注不会迷路