Java AQS 是什么

2 阅读2分钟

Java AQS 是什么

一文搞懂AQS

AQS详解

什么是AQS

AQS(AbstractQueuedSynchronizer)是一个用于构建锁和同步器的框架。它通过一个先进先出的等待队列管理多个线程的同步操作。AQS 提供了资源状态管理、线程排队管理和模板方法等核心功能。

核心思想

AQS 的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制。AQS 使用 CLH 队列锁实现这一机制,将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点(Node)来实现锁的分配。

主要功能

  1. 资源状态管理:AQS 使用一个 volatile 类型的整数变量(state)来表示同步状态。子类可以定义该状态的具体意义,例如对于独占锁,state 表示锁的持有状态(0 表示未持有,1 表示持有)。
  2. 线程排队管理:AQS 使用一个 FIFO 等待队列来管理处于等待状态的线程。当线程请求无法获取同步状态时,会被加入等待队列。
  3. 模板方法:AQS 提供了一系列模板方法,子类可以通过实现这些方法来定义具体的同步机制。

应用示例

ReentrantLock

ReentrantLock 是一种基于 AQS 实现的可重入独占锁。它有两种模式:公平模式和非公平模式。

public class AQSDemo {

private static int num;

public static void main(String[] args) {

ReentrantLock lock = new ReentrantLock();

new Thread(() -> {

lock.lock();

try {

Thread.sleep(1000);

num += 1000;

System.out.println("A 线程执行了1秒, num = " + num);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}, "A").start();

new Thread(() -> {

lock.lock();

try {

Thread.sleep(500);

num += 500;

System.out.println("B 线程执行了0.5秒, num = " + num);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}, "B").start();

new Thread(() -> {

lock.lock();

try {

Thread.sleep(100);

num += 100;

System.out.println("C 线程执行了0.1秒, num = " + num);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}, "C").start();

}

}

复制

CountDownLatch

CountDownLatch 是一种基于 AQS 实现的同步工具,它允许一个或多个线程等待一组操作完成。

public class CountDownLatchExample {

private static final int THREAD_COUNT = 550;

public static void main(String[] args) throws InterruptedException {

ExecutorService threadPool = Executors.newFixedThreadPool(300);

final CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT);

for (int i = 0; i < THREAD_COUNT; i++) {

final int threadNum = i;

threadPool.execute(() -> {

try {

test(threadNum);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

countDownLatch.countDown();

}

});

}

countDownLatch.await();

threadPool.shutdown();

System.out.println("finish");

}

public static void test(int threadnum) throws InterruptedException {

Thread.sleep(1000);

System.out.println("threadNum:" + threadnum);

Thread.sleep(1000);

}

}

复制

通过这些示例,可以看到 AQS 在 Java 并发编程中的重要性和广泛应用。