ReentrantLock.NonfairSync继承自内部类Sync,而Sync继承自AbstractQueuedSynchronizer。
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
// 首先尝试立即获取锁,获取成功,则将自身设定为 独占模式的同步器 的拥有者
// 如果获取失败,则通过调用AQS.acquire()方法来抢占锁
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
NonfairSync非公平锁实现的AQS.tryAcquire内的nonfairTryAcquire方法具体如下:
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
// 获取独占资源的状态
int c = getState();
// 如果state为0,表示其它线程并未占用独占资源,当前线程可以直接抢占
if (c == 0) {
if (compareAndSetState(0, acquires)) {
// 抢占独占资源成功后,将当前线程设为独占资源的拥有者
setExclusiveOwnerThread(current);
return true;
}
}
// 如果独占资源被其它线程所占有,则判断占用独占资源的线程是否是自身
else if (current == getExclusiveOwnerThread()) {
// 可重入锁的意味
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 设定占据独占资源的线程数(state)
setState(nextc);
return true;
}
// 被不是自身的其它线程占用了独占资源,所有tryAcquire失败,返回false
return false;
}
AQS.acquire方法如下:
public final void acquire(int arg) {
// 如果竞争锁资源失败,则阻塞当前线程
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
通过addWaiter()方法,为当前线程以EXCLUSIVE模式构建等待节点,添加到CLH队列尾部。addWaiter()方法返回当前线程的Node。
紧接着,acquireQueued(Node node)方法以当前线程的node节点,通过独占不间断模式获取CLH队列中的等待线程。acquireQueued(Node node)方法如下:
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// 获取当前线程节点在CLH队列中的前继节点
final Node p = node.predecessor();
// 如果前继节点是头指针,并且可以获取到资源锁,则将自身线程节点设定为头节点
// AQS.tryAcquire方法,由子类具体实现
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 表明当前线程节点并非是 CLH 队列中唯一需要等待获取资源锁的线程
// shouldParkAfterFailedAcquire返回true,则表明当前线程节点应当阻塞
// parkAndCheckInterrupt返回true表明当前线程节点应当中断
// 综上,当前线程节点获取资源锁失败
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}