显示锁ReentrantLock的内部同步依赖于AQS(AbstractQueuedSynchronizer),因此,分析ReentrantLock必然涉及AQS。
本文假设读者已熟练掌握AQS的基本原理(参考AQS的基本原理),通过分析ReentrantLock#lock()与ReentrantLock#unlock()的实现原理,用实例帮助读者理解AQS的等待队列模型。
JDK版本:oracle java 1.8.0_102
接口声明
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
ReentrantLock对标内置锁,实现了Lock接口。忽略Condition相关,主要提供lock、unlock两种语义,和两种语义的衍生品。
实现原理
继承AQS
本文中的“继承”指“扩展extend”。
AQS复习
AQS并提供了多个未实现的protected方法,留给作者覆写以开发不同的同步器:
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
...
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
...
}
而其他非私有方法则使用final修饰,禁止子类覆写。
继承
ReentrantLock支持公平、非公平两种策略,并通过继承AQS实现了对应两种策略的同步器NonfairSync与FairSync。ReentrantLock默认使用非公平策略,即NonfairSync:
public ReentrantLock() {
sync = new NonfairSync();
}
...
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
...
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
...
abstract void lock();
final boolean nonfairTryAcquire(int acquires) {
...
}
protected final boolean tryRelease(int releases) {
...
}
final ConditionObject newCondition() {
return new ConditionObject();
}
...
}
...
先不追究细节。下面以默认的非公平策略为例,讲解lock和unlock的实现。
lock
public void lock() {
sync.lock();
}
非公平策略下,sync指向一个NonfairSync实例。
static final class NonfairSync extends Sync {
...
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
...
}
ReentrantLock用state表示“所有者线程已经重复获取该锁的次数”。当state等于0时,表示当前没有线程持有该锁,因此,将state CAS设置为1,并记录排他的所有者线程ownerThread(ownerThread只会在0->1及1->0两次状态转换中修改);否则,state必然大于0,则尝试再获取一次锁。ownerThread将在state大于0时,用于判断重入性。
- 排他性:如果线程T1已经持有锁L,则不允许除T1外的任何线程T持有该锁L
- 重入性:如果线程T1已经持有锁L,则允许线程T1多次获取锁L,更确切的说,获取一次后,可多次进入锁。
二者结合,描述了ReentrantLock的一个性质:允许ownerThread重入,不允许其他线程进入或重入。
acquire
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
...
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
...
}
改写:
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
...
public final void acquire(int arg) {
if (tryAcquire(arg)) {
return;
}
Node newNode = addWaiter(Node.EXCLUSIVE);
boolean interrupted = acquireQueued(newNode, arg);
if (interrupted) {
selfInterrupt();
}
}