了解Java并发同步框架:AQS(AbstractQueuedSynchronizer)
什么是AQS
AQS(AbstractQueuedSynchronizer)是Java并发编程中一个重要的同步框架,提供了一个实现锁和其他同步器的基础。它通过FIFO队列来管理线程的争用,为开发者提供了便捷且高效的工具来实现自己的同步器,如ReentrantLock, CountDownLatch等。
AQS的核心思想
AQS的核心思想是使用一个FIFO等待队列来管理获取锁的线程。每个请求锁的线程会被包装成一个节点(Node),然后加入到这个等待队列中。当线程获取到锁时,它会被标记为head节点,其他等待的线程则会按照队列顺序依次尝试获取锁。
状态管理
AQS使用一个整型变量state来表示同步状态。对于独占锁(如ReentrantLock),state值为0表示未锁定状态,1表示锁定状态。而对于共享锁(如CountDownLatch),state的值可以表示当前计数。
队列节点
AQS的内部队列是一个双向链表,每个节点表示一个线程请求。节点包含了线程的引用,以及状态信息(如是否被取消)。
AQS的实现机制
独占模式
在独占模式下,只有一个线程能持有锁,其他线程将会被阻塞,直到锁被释放。AQS提供了acquire
和release
方法来管理独占锁的获取和释放。
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
共享模式
共享模式允许多个线程同时获取锁。例如,Semaphore和CountDownLatch就是基于共享模式实现的。AQS通过acquireShared
和releaseShared
方法来管理共享锁。
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
队列操作
AQS的关键在于如何管理等待队列。当一个线程请求锁时,它会被加入到队列的末尾,并进入等待状态。AQS通过enq
方法来进行队列的插入操作,通过dequeue
来进行队列的移除操作。
AQS的应用实例
ReentrantLock
ReentrantLock是Java中常用的独占锁,它使用AQS来实现同步控制。以下是ReentrantLock的简化实现示例:
public class ReentrantLock {
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
protected final boolean isHeldExclusively() {
return getState() == 1;
}
protected final boolean tryRelease(int releases) {
if (getState() == 0) throw new IllegalMonitorStateException();
setState(0);
return true;
}
protected final boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
}
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
} else {
acquire(1);
}
}
}
public ReentrantLock() {
sync = new NonfairSync();
}
public void lock() {
sync.lock();
}
public void unlock() {
sync.release(1);
}
}
参考链接
- AQS源码:AbstractQueuedSynchronizer.java
- Java并发编程实践:Java Concurrency in Practice