Java并发编程:深入理解AQS原理
AQS(AbstractQueuedSynchronizer)是Java并发包的核心基础,ReentrantLock、CountDownLatch、Semaphore等都基于AQS实现。
AQS核心设计
同步状态
AQS使用一个int类型的state变量表示同步状态:
// 同步状态,使用volatile保证可见性
private volatile int state;
// 获取状态
protected final int getState() {
return state;
}
// 设置状态
protected final void setState(int newState) {
state = newState;
}
// CAS更新状态
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
CLH队列
AQS内部维护一个FIFO双向队列来管理等待线程:
- 节点包含线程引用、等待状态、前后指针
- 首节点(head)表示当前持有资源的线程
- 后续节点等待获取资源
独占模式实现
获取资源
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
流程:
- tryAcquire()尝试获取资源(子类实现)
- 失败则创建节点加入队列
- acquireQueued()自旋等待获取资源
- 如果被中断,恢复中断状态
释放资源
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
实战建议
- 理解原理:掌握AQS有助于正确使用并发工具
- 自定义同步器:需要时可以基于AQS实现自定义同步组件
- 注意陷阱:避免死锁、正确处理中断
小结
AQS通过状态管理和队列实现,提供了灵活的同步框架。理解其原理对于编写高质量并发程序至关重要。