首先我们先搞明白继承关系, ReentrantLock的内部类FairSync extends Sync extends AbstractQueuedSynchronizer
-
ReentrantLock中的内部类FairSync中lock方法,调用了AbstractQueuedSynchronizer中的acquire()方法。
final void lock() { acquire(1); }
- acquire()方法中调用了子类FairSync中tryAcquire()方法和自身的acquireQueued()方法。
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
-
我们先看tryAcquire(),先判断state是否为0,如果为0就执行上面提到的lock方法的前半部分,通过CAS操作将state的值从0变为1,否则判断当前线程是否为exclusiveOwnerThread,然后把state++,也就是重入锁的体现,我们注意前半部分是通过CAS来保证同步,后半部分并没有同步的体现,原因是:后半部分是线程重入,再次获得锁时才触发的操作,此时当前线程拥有锁,所以对ReentrantLock的属性操作是无需加锁的。如果tryAcquire()获取失败,则要执行addWaiter()向等待队列中添加一个独占模式的节点。
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//公平锁和非公平锁的区别:公平锁会多一个!hasQueuedPredecessors()判断
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
4.如果tryAcquire()返回false了,那么此时就得acquireQueued()方法。首先利用addWaiter()方法将线程封装成一个节点,加入了同步队列。在acquireQueued()方法中,如果当前节点的前驱节点是头节点,那么就调用tryAcquire()获取同步状态。
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);
}
}