“ 上一篇文章分析了锁框架的AQS的源码,今天我们来分析一种具体的锁:重入锁ReentrantLock的源码,前面我们也说到ReentrantLock内部最重要的实现是基于AQS做的”
在分析重入锁代码之前,我们需要先知道重入锁ReentrantLock分为公平锁和非公平锁(通过构造函数创建不同的锁),它的内部基于AQS实现抽象类Sync同步器(在AQS文章中我们谈论过)。
01
—
首先我们看一下ReentrantLock的内部抽象类Sync。Sync在ReentrantLock中承担着基石的作用,在它的内部实现一系列的方法用于ReentrantLock定义公平锁和非公锁,代码中注释关于Sync说的很清楚了(自认为)。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
abstract void lock();
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
* 非公平锁获取
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//getState()是AQS的方法,用于返回锁状态
int c = getState();
//如果c==0说明锁没有被占有
if (c == 0) {
//开始比较和更新state的状态
if (compareAndSetState(0, acquires)) {
//设置锁的拥有者为当前锁,setExclusiveOwnerThread是AbstractOwnableSynchronizer的方法
setExclusiveOwnerThread(current);
return true;
}
}
//如果c!=0,判断锁是否是当前线程拥有
else if (current == getExclusiveOwnerThread()) {
//既然锁的拥有者是当前线程,那么c+1,这样释放锁的时候,不会立刻释放,锁的持有者仍是当前线程,类似与偏向锁
int nextc = c + acquires;
//超过最大锁计数
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//更新state
setState(nextc);
return true;
}
return false;
}
//释放锁
protected final boolean tryRelease(int releases) {
//
int c = getState() - releases;
//当前线程不是锁的拥有者,抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
//
boolean free = false;
//c==0,说明这个线程获取锁一次,此时将锁的拥有者设为null,因为如果获取两次,c必然大于0,上面nonfairTryAcquire方法中同一线程多次获取锁,会增加
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
//c!=0 更新c的值,返回false
setState(c);
return free;
}
// 是否占有锁
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
//关于ConditionObject这里先不说
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
//获取拥有锁的线程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
//如果拥有锁返回持有数量,否则返回0
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
//是否上锁,getState!=0的情况表明已经上锁
final boolean isLocked() {
return getState() != 0;
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it).反序列化
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
关于Sync上面我们已经了解过,现在我们再来看一下基于Sync实现的公平锁FairSync和非公平锁NonfairSync
//非公平锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
//lock是Sync中已经定义好
final void lock() {
//首先判断锁是否被获取,没有的化更新state的状态
if (compareAndSetState(0, 1))
//设置锁的拥有者为当前线程
setExclusiveOwnerThread(Thread.currentThread());
else
//被获取的情况下,调用AQS的acquire方法,这个方法前面我们已经分析过:
//首先获取锁,失败的情况下调用addWaiter,将该线程存放在节点中,等待被执行
//trrAcquire已被重写,实际上调用nonfairTryAcquire方法
acquire(1);
}
//nonfairTryAcquire方法在上面Sync中我们已经分析过
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
公平锁:
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
//不同于非公平锁,这里直接使用acquire方法,走AQS的业务逻辑
//但是AQS中的tryAcquire方法被重写。
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
//重写AQS方法
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;
}
}
//下面代码跟Sync中作用一样
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
既然基于AQS的同步器Sync以及公平锁和非公平锁代码我们已经分析过(我觉得核心还是要去分析AQS的代码,然后才能理解重入锁代码逻辑)。下面我们再来看一下ReentrantLock的方法:
首先是它的两个构造方法
//无参构造方法,默认非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
//带参构造方法,根据参数实现公平锁或者非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
然后是lock方法
//sync在开始已被定义,何种锁也在构造方法中确定,这里直接调用Sync实现类的lock方法
public void lock() {
sync.lock();
}
既然有lock方法那必然有unlock方法
//释放锁
public void unlock() {
sync.release(1);
}
lock和unlock是我们常用的两个方法,但是ReentrantLock还存在其他的方法,我们大致的来看一下:
lockInterruptibly
//在等待时由其它线程调用等待线程的Thread.interrupt方法来中断等待线程的等待而直接返回,
//这时不用获取锁,而会抛出一个InterruptedException
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
tryLock
//以非公平锁的形式尝试获取锁,这也说明了为什么nonfairTryAcquire定义在Sync中,以及他叫可重入锁
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
tryLock(long timeout, TimeUnit unit)
//试图以独占模式获取对象,如果被中断则中止,如果到了给定超时时间,则会失败
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
newCondition
public Condition newCondition() {
return sync.newCondition();
}
getHoldCount :获取当前线程持有锁次数
public int getHoldCount() {
return sync.getHoldCount();
}
isHeldByCurrentThread:是否是当前线程占有锁
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
isLocked:锁是否被占有
public boolean isLocked() {
return sync.isLocked();
}
isFair:是否公平锁
public final boolean isFair() {
return sync instanceof FairSync;
}
getOwner:获取持有锁的线程
protected Thread getOwner() {
return sync.getOwner();
}
hasQueuedThreads:用于查询是否有线程正在等待获取指定的对象监视器
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
hasQueuedThread(Thread thread) :用来查询指定的线程是否正在等待获取指定的对象监视器
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
getQueueLength()方法用于获取正等待获取此锁定的线程估计数。注意"估计"两个字,因为此方法遍历内部数据结构的同时,线程的数据可能动态变化
public final int getQueueLength() {
return sync.getQueueLength();
}
getQueuedThreads:返回一个 collection,包含可能等待获取的线程。因为在构造此结果的同时实际的线程 set 可能动态地变化,所以返回的 collection 仅是尽力的估计值
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
hasWaiters:查询是否有线程正在等待与此锁有关的condition条件
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
getWaitQueueLength:类似getQueueLength(),不过此方法的前提是condition
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
getWaitingThreads:返回一个collection,它包含可能正在等待与此锁相关给定条件的那些线程,因为构造结果的时候实际线程可能动态变化,因此返回的collection只是尽力的估计值
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}