三. 原理
1. lock()
我们先以 ReentrantLock.lock() 来看简单加锁的场景;
// ----------------------------------- ReentrantLock ----------------------------------------
public void lock() {
sync.lock();
}
// ----------------------------------- FairSync ----------------------------------------
final void lock() {
// 调用 acquire(1)
acquire(1);
}
// ------------------------------- AbstractQueuedSynchronizer ----------------------------------
public final void acquire(int arg) {
// 1. 先执行 tryAcquire(arg) 尝试获取锁
// 获取到了锁返回 true,直接退出该方法
// 没有获取到锁返回 false, 调用 acquireQueued(),表示将当前线程加入阻塞队列阻塞等待获取锁
// 2. acquireQueued() 表示将当前线程加入阻塞队列阻塞等待获取锁
// 正常获取到锁返回 false,直接退出该方法
// 如果外部中断了该线程,也会获取到锁,但是返回 true,执行方法体里的 Thread.currentThread().interrupt();
// 了解中断即可
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
Thread.currentThread().interrupt();
}
主要是 tryAcquire(arg) 和 acquireQueued(),我们重点看下这两个方法做了啥;
1.1 tryAcquire(arg)
tryAcquire(arg) 如下;
// ----------------------------------- ReentrantLock ----------------------------------------
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 1. 如果当前没有等待的线程,CAS 获取锁
// 获取锁成功的话讲当前线程设置为 exclusiveOwnerThread,表示独占该锁
// 并返回 true,表示获取了锁
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 2. state != 0,表示有线程持有了锁
// 由于 ReentrantLock 是可重入锁,检查持有锁的线程是否是当前线程
// 如果是的话 state++,并返回 true,表示获取到了锁
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
// 3. 没有获取到锁,返回 false
return false;
}
1.2 acquireQueued()
acquireQueued(),该方法表示以不可中断的方式加了阻塞等待队列,可以看到线程中断不影响它获取到锁;
// ------------------------------- AbstractQueuedSynchronizer ----------------------------------
/**
* 以不可中断的方式加了阻塞等待队列
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} 如果在等待期间发生了中断返回 true,没有发生中断的话返回 false
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 1. 死循环自旋
// 除非线程放弃获取锁,正常情况下一定能获取到锁
for (;;) {
final Node p = node.predecessor();
// 2. 如果当前节点是头结点的后继节点,尝试获取锁,并返回 interrupted 值
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
failed = false;
return interrupted;
}
// 3. 将当前节点加入阻塞队列阻塞,直到被唤醒
// parkAndCheckInterrupt() 会执行 LockSupport.park(this);
// 正常唤醒 LockSupport.unpark() 时,方法返回 false,interrupted 还是 false
// 如果是中断唤醒,方法返回 true,进入方法体,interrupted = true
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
// ------------------------------- AbstractQueuedSynchronizer ----------------------------------
private final boolean parkAndCheckInterrupt() {
// 1. 阻塞挂起当前线程
LockSupport.park(this);
// 正常唤醒 LockSupport.unpark() 时,返回 false
// 如果是中断唤醒,返回 true,并情况中断标示位,使 Thread.isInterrupted() == false
return Thread.interrupted();
}
2. unlock()
unlock() 表示释放锁,我们以公平锁来看下 unlock();
// ----------------------------------- ReentrantLock ----------------------------------------
public void unlock() {
// 执行 sync.release(1)
sync.release(1);
}
// ------------------------------- AbstractQueuedSynchronizer ----------------------------------
public final boolean release(int arg) {
// 尝试释放锁
// 完全释放了锁的话,唤醒阻塞队列中的后继线程,并返回 true
// 没有完全释放锁,返回 false
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
2.1 tryRelease(releases)
我们知道 ReentrantLock 是可重入锁,释放锁需要使 state == 0 才算完全释放锁;
// ----------------------------------- ReentrantLock ----------------------------------------
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 1. 注意!!!
// 如果当前线程没有持有锁,调 lock.unlock() 走到这里会抛出 IllegalMonitorStateException 异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
// 2. 完全释放掉锁,返回 true
// 没有完全释放掉锁,返回 false
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
3. tryLock()
tryLock() 如下;
// ----------------------------------- ReentrantLock ----------------------------------------
public boolean tryLock() {
// 以不公平锁的方式获取锁
return sync.nonfairTryAcquire(1);
}
3.1 nonfairTryAcquire(acquires)
Sync 的 nonfairTryAcquire(acquires) 如下:
// ------------------------------------- Sync ------------------------------------------
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 1. 直接尝试去获取锁,获取锁成功的话返回 true
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 2. 竞争锁失败,看当前线程是否已经持有锁
// 是的话 state++,返回 true
// 否的话返回 false,竞争锁失败
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. tryLock(timeout)
ReentrantLock 的 tryLock(timeout) 如下,它会抛出受检异常 InterruptedException,说明和中断有关;
// ----------------------------------- ReentrantLock ----------------------------------------
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
4.1 tryAcquireNanos(timeout)
// ----------------------------------- AbstractQueuedSynchronizer -------------------------------
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
// 1. 如果线程已经中断了,直接抛出异常
if (Thread.interrupted())
throw new InterruptedException();
// 2. 先尝试直接获取锁,调用 tryAcquire(arg)
// 获取锁失败的话进入阻塞等待队列中挂起 timeout 时间,期间可能会被唤醒获取锁,调用 doAcquireNanos()
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
// 1. 死循环自旋
for (;;) {
// 2. 如果当前节点是头结点的后继节点,尝试获取锁,返回 true,表示获取到锁
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
// 3. 如果 deadline 已到,返回 false,表示获取锁失败
if (nanosTimeout <= 0L)
return false;
// 4. 当前线程进入阻塞等待队列中等待 timeout 时间
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
// 5. 需要比较 Thread.interrupted() 的值
// 如果线程被中断了,该值为 true,并往外抛出异常
// 其他情况,正常唤醒、parkNanos() 时间到,该值都是 false
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
至此,ReentrantLock 分析完毕。