ReentrantLock是一个可以重入的互斥(独占)锁,支持公平锁和不公平锁(默认)。他的内部实现主要是有一个Sync内部类,具体情况我们注意阅读源码进行分析。
1.Sync
Sync是一个实现了AQS的内部类,他还有FairSync和NonFairSync两种实现。Sync是这个锁的基础,使用了AQS中的state来表示当前拥有的锁的数量(因为是重入锁,可能被多次lock)。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*执行非公平的tryLock,tryAcquire是在子类中实现的,但是都需要nonfair来尝试
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();//获取当前状态,AQS方法
if (c == 0) {
//如果state为0,表示锁没有被获取,则尝试获取锁(用CAS设置State)
//获取成功就设置拥有锁的线程为当前线程
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}//如果state不为0(锁未被释放),如果当前线程就是获取锁的线程,那么就再设置一次state
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
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;
//如果本次release之后,state为0,就将拥有锁的线程设置为null。
//否则就是设置state为新的值。
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
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();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
//如果没有线程拥有锁(state为0)就返回null,否则返回拥有锁的线程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
//返回当前锁的重入的数量
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
//state不为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
}
}
非公平锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
//设置状态为1,如果失败就调用AQS的acquire,
//acquire的实现就是先tryAcquire(也就是紧接下面的方法),不成功再入队等待
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
//调用Sync里面的方法,当前获取锁的是本线程,就重入,否则就返回false
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
公平锁
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
//直接调用acquire(1),非公平是自己先尝试获得锁,获得不了再acquire
//他的acquire中tryAcquire是公平版本的实现
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
//公平版本的tryAcquire,只有在递归调用,或者没有其他等待者或者自己是第一的时候获取锁
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//如果state为0(没有锁),hasQueuedPredecessors()判断自己是不是等待最久的(AQS方法)
//如果是等待最久的,就尝试设置state,设置成功了就表明拥有了锁。
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}//state不为0,就查看是不是当前线程拥有锁,是的话就重入锁
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
2.Lock中的一些方法
构造函数,不带参数就是非公平锁,带参数,true就是公平锁,
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public 方法,lock就是尝试获取锁,调用内部类的方法
public void lock() {
sync.lock();
}
//以响应中断的模式获取锁,先调用AQS的acquireInterruptibly()方法,
//这个方法中会调用子类的tryAcquire()方法,如果失败,再入队等待锁
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
tryLock(),获取锁失败(设置state失败或者当前已经有线程拥有锁),就返回false,而不是入队等待
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
unLock()释放锁
//release是AQS的方法,先调用子类的tryRelease(),然后在唤醒队列中的后继节点
public void unlock() {
sync.release(1);
}
这就是ReentrantLock的基本实现,可以看到,除了自己完成了几个模板方法(对state进行判断),其他基本都是调用AQS的方法。
Condition就完全没有自己实现,完全依赖AQS的实现。