前言
AQS是java.util.concurrent.locks包中的一个抽象类,全称AbstractQueuedSynchronizer,直译过来就是抽象队列同步器。它是并发用来构建锁和其他同步组件的基础框架。下面是在JDK源码中对于AQS的解释:
AQS支持独占或者共享的模式去获取锁,其核心思想是:如果被请求的共享资源空闲,那么就将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态;如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中。
原理
AQS类内部有一个volatile修饰的state和一个双向链表Node(静态内部类),每个node内部又有一个变量thread来记录当前线程。这个state就是用来记录锁状态的,如果是空闲状态就为0,否则就是1或以上,多线程争用资源被阻塞时会进入此队列。
从ReentrantLock.lock函数开始走进AQS:
获取锁。
public void lock() {
sync.lock();
}
lock函数分别有公平锁和非公平锁两种实现方式,以公平锁为例,lock函数直接调用acquire(1)尝试获取锁。
final void lock() {
acquire(1);
}
以独占模式获取,忽略中断。通过调用tryAcquire}来实现,成功就直接返回。否则线程排队,可能重复阻塞和解除阻塞,调用 tryAcquire直到成功。
public final void acquire(int arg) {
// 尝试获取锁
if (!tryAcquire(arg) &&
// 上面获取锁失败就执行这两个方法
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
进入tryAcquire方法查看:
该函数就是判断state状态,如果线程是空闲状态就直接获取锁,如果不是空闲状态但已经被当前线程持有就将state+1,否则就返回false;
protected final boolean tryAcquire(int acquires) {
// 当前线程
final Thread current = Thread.currentThread();
// 获取锁状态 0就是空闲,1就是以及被占有
int c = getState();
// 如果锁状态时空闲
if (c == 0) {
// 查看阻塞队列前是否有线程在等待
if (!hasQueuedPredecessors() &&
// 如果没有线程在阻塞,就调用cas方法更新state
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 如果锁已经被当前线程占有就将state+1
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
如果尝试获取锁失败就执行 acquireQueued(addWaiter(Node.EXCLUSIVE), arg))两个方法,addWaiter为当前线程和给定模式创建和排队节点。节点绑定当前线程。
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
acquireQueued方法以独占不间断模式获取已在队列中的线程。由条件等待方法和获取使用。遍历整个链表不断尝试获取锁
final boolean acquireQueued(final Node node, int arg) {
// 失败状态标志位
boolean failed = true;
try {
// 中断标志位
boolean interrupted = false;
// 一直遍历节点
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}