之前我们分析过AbstractQueuedSynchronizer的独占锁的获取与释放的源码,ReentrantLock是基于AbstractQueuedSynchronizer的独占锁实现的锁,今天我们来分析它各种加锁的方式,比如公平锁,非公平锁,可中断加锁,一定时间加锁等。
一:公平锁与非公平锁
public class ReentrantLock implements Lock, java.io.Serializable {
private final Sync sync;
//内部的Sync继承了AQS,Sync有两个子类,如下
abstract static class Sync extends AbstractQueuedSynchronizer {
...
}
// 非公平实现
static final class NonfairSync extends Sync{
...
}
// 公平实现
static final class FairSync extends Sync {
...
}
}
ReentrantLock的内部类Sync 继承了AbstractQueuedSynchronizer ,并且有公平和非公平两种实现:
先来看公平锁的实现:
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
}
公平锁lock()直接调用了AQS的acquire(1)方法,我们看看它重写的tryAcquire()是什么样的:
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 首先获取当前锁的状态
int c = getState();
// c = 0 说明当前锁没被任何线程占用, 可以尝试获取锁
if (c == 0) {
// 因为是公平锁, 所以在获取锁之前首先看看队列中有没有排在自己前面的Node
if (!hasQueuedPredecessors() &&
// 如果没有人在排队, 则通过CAS方式获取锁
compareAndSetState(0, acquires)) {
// 获取成功,把占用锁的线程设为自己
setExclusiveOwnerThread(current);
return true;
}
}
// 说明state不0,锁被某个线程获得了
// 因为是可重入锁,所以需要判断获取锁的是不是当前的线程,是的话把状态加acquires
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new